DAY 13用户新闻收藏功能实现和页面渲染

收藏按钮的渲染

在我们新闻详情页中我们需要对收藏按钮进行不同的渲染

第一种是收藏

 

 

 第二种是已收藏:

 

 

 我们先来进行简单的分析,这是关于新闻详情页的渲染,所以我们需要来到我们

渲染详情页的视图函数中进行代码的编写,收藏功能是针对登录用户的操作,未登录用户

是不能进行的。所以我们需要先判断用户的登录状态,没有登录就不能进行第二种已收藏,

直接是第一种的渲染,还有就是对登录用户的信息进行判断,查看是否收藏过这条新闻,如果收藏

过我们就展示第二种,如果没有收藏就展示第一种。

而这里渲染第一种的情况有两种,没有登录或者登录后没有收藏,所以我们可以先将展示第一种的

判断条件设定为FLASE,只有满足了登录且收藏后才是TRUE。也就是第二种渲染

大致理清思路后我们就开始代码的编写

先在视图函数中写人注释

 

 

 然后是代码:

# 4. 收藏相关展示
    is_collected = False   #设定默认为FALSE
    if user:   #用户已登录
        if news in user.collection_news : #用户已收藏
            is_collected = True    
# 生成保存用户变量的上下文并传到前台进行相关判断处理
    context = {
        "user": user,
        "news_click_list": news_click_list,
        "news":news.to_dict(),
        "is_collected":is_collected   #生成上下文给前端
    } 

 

前端的代码为:

  <a href="javascript:;" class="collected block-center" data-newid="{{ news.id }}" style="display: {% if is_collected %} block
  {% else %} none {% endif %};"><span class="out">已收藏</span><span class="over">取消收藏</span></a>

  <a href="javascript:;" class="collection block-center" data-newid="{{ news.id }}" style="display: {% if is_collected %} none
   {% else %} block {% endif %};">收藏</a> 

 校验:我们可以通过往用户和新闻创建的第三张收藏表里面加入测试数据,也就是当前的用户ID和新闻ID手动加到

数据库中,然后刷新页面查看按钮是否变成已收藏来完成

用户收藏功能的实现以及取消收藏

当我们完成了收藏按钮的渲染,我们还需要完成当登录用户点击

按钮时完成新闻的收藏,用户和新闻是多对对的关系,所以我们需要操作建立多对多关系的第三张表,

也就是我们的用户新闻收藏表中点击收藏时添加我们的数据,以及点击取消收藏时对相应数据的删除

这里是一个新的接口,所以我们需要建立一个符合接口规范的新的视图函数:

 

 视图函数创建在我们的news模块文件夹里,因为是新闻页的内容,写在渲染详情页视图的后面

安装接口设计图来写URL和函数名,请求方式为post,记得设置

完成之后还是写文档注释,实现的功能:

 

 然后在先整理思路后写上文字 步骤,简单分析:

首先这个功能是用户登录后才有的,所以在接收参数之前判断用户是否登录,

如果没有,我们就不需要进行后续的步骤,直接返回错误码和错误信息就行,让前台再根据错误码进行

相应的操作,比如弹出提示登录信息或者直接跳转到登录界面

这里补充一下用户校验过滤器的问题:

关于用户校验我们使用了过滤器,但是我们在之前的渲染页面也使用了过滤器

这就导致了我们视图的__name__变成了统一的值,也就是过滤器返回的wrapper。

视图函数是不允许这种情况的发生的,所以我们需要将__name__的值变回原来的视图函数所生成的值

需要在我们的过滤器中加入一个过滤器来完成:

 

 warps 完成的就是把__name__改回原来的值,设置后就没问题了。

完成校验用户的登录状态之后,接下来才是接收数据(new_id,action),action对应了不同的参数,分别为取消收藏和

收藏,也就是不同的操作

接收完成后进行校验,先判断参数是否齐全,然后校验接收到的news_id 的数据类型,然后再判断传入的action是否合法,是否为指定的

两个值的其中一个,最后才是进行数据库查询,我们需要将查询操作放在最后进行,这样省时。如果先进行数据库查询,查询后其他的数据错误的话又要再次进行查询后再

次进行后面的操作,放在后面当前面发送错误就不需要操作数据库了。查询news_id对应的新闻是否存在

完成校验之后就是对不同action的值进行不同的操作,最后返回结果就完成了,完成分析后对代码进行编写

 

 第一步

# 1.判断用户是否登录
    user = g.user
    if not user :
        return jsonify(errno=RET.SESSIONERR,errmsg="用户未登录") 

 

这里使用过滤器后直接通过g变量获取就行,没有返回None ,然后再进行判断返回结果

第二步

# 2. 接收参数(news_id, action)
    news_id = request.json.get("news_id")
    action = request.json.get("action") 

这里接收的是json数据,进行相应的查询代码查询就行(request.json.get),没有的包记得导入。

第三步

# 3.校验参数
    # 3.1判断参数是否传齐
    if not all([news_id,action]):
        return jsonify(errno=RET.PARAMERR,errmsg="参数缺失")
    # 3.2判断news_id是否为整形
    try:
        news_id = int(news_id)
    except Exception as e :
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR,errmsg="参数错误")
    # 3.3判断action是否合法
    if action not in ["collect","cancel_collect"]:
        return jsonify(errno=RET.PARAMERR,errmsg="非法参数")
    # 3.4判断新闻是否存在
    try:
        news = News.query.filter_by(id = news_id).first()
    except Exception as e :
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR,errmsg="数据库读取失败")
    if not news :            #对新闻是否存在进行处理
        return jsonify(errno=RET.NODATA,errmsg="新闻未找到") 

 

这里通过强转来判断整形,当强转失败也就是传入了不符合的数据类型并作出处理。action的判断创建了一个内表,通过判断

传入的action的值是否在内表里来进行,这样拓展性更强,而且比起 == 的判断代码量少。

通过news_id来进行查询并对结果进行判断,不要忘记对结果进行判断处理这一步

第四步

# 4.通过action来进行收藏操作
    if action == "collect" :
        if news not in user.collection_news: #判断新闻对象是否在列表里
            user.collection_news.append(news) #往新闻对象的列表里加入新的新闻对象
    else:
        if news in user.collection_news:
            user.collection_news.remove(news)
    try:
        db.session.commit()         #提交到数据库
    except Exception as e :
            current_app.logger.error(e)
            db.session.rollback()              #修改数据,事物,回滚
            return jsonify(errno=RET.DBERR,errmsg="操作数据库失败")

  

action接收到的值只有两个,所以这里可以用双分支来进行处理,通过判断里再判断对逻辑步骤进行说明,比起合并这样更能

展现每一步的实现的思路和用意。

首先通过双分支来对不同的值进行处理,collect表示的是收藏该新闻,也就是在我们对象属性所参生的新闻对象列表里加入查询到的

新闻对象,用append来进行列表对象的添加。首先还是要先判断该对象是否在列表里,没有再进行添加。

user.collection_news所产生的数据为有新闻对象的列表,我们查询的news也是一个新闻对象,这里是对多对多功能的使用,对应模型User类的获取数据的

字段,这个字段只是方便我们操作第三张表来获取数据,并不是存在的字段

 

 

 然后就是例外的值,也就是取消收藏,从类表中把对应的新闻对象移除(remove),也需要先判断列表中新闻是否存在。

完成记得提交到数据库,而且对数据进行了操作,要设置回滚,操作失败把数据还原到之前。

第五步

 # 5.返回数据
    return jsonify(errno=RET.OK,errmsg="成功")

 

 返回成功的码给前台进行判断执行js 文件,完成后台的修改之后对前端js文件进行修改

前端代码

找到详情页detailHTML的detail.js文件,然后进行代码的修改,也就是覆盖粘贴

 

// 收藏
    $(".collection").click(function () {
        // 参数:要收藏哪条新闻
        var params = {
            'news_id':$(this).attr('data-newid'),
            'action':'collect'
        };

        $.ajax({
            url: '/news/news_collect',
            type: 'post',
            data: JSON.stringify(params),
            contentType: 'application/json',
            headers: {'X-CSRFToken':getCookie('csrf_token')},
            success:function (response) {
                if (response.errno == "0") {
                    // 收藏成功,隐藏收藏按钮
                    $(".collection").hide();
                    // 显示取消收藏按钮
                    $(".collected").show();
                }else if (response.errno == "4101"){
                    $('.login_form_con').show();
                }else{
                    alert(resp.errmsg);
                }
            }
        });
    });

    // 取消收藏
    $(".collected").click(function () {
        // 参数:要取消收藏哪条新闻
        var params = {
            'news_id':$(this).attr('data-newid'),
            'action':'cancel_collect'
        };

        $.ajax({
            url: '/news/news_collect',
            type: 'post',
            data: JSON.stringify(params),
            contentType: 'application/json',
            headers: {'X-CSRFToken':getCookie('csrf_token')},
            success:function (response) {
                if (response.errno == "0") {
                    // 取消收藏成功,隐藏收藏按钮
                    $(".collection").show();
                    // 显示取消收藏按钮
                    $(".collected").hide();
                }else if (response.errno == "4101"){
                    $('.login_form_con').show();
                }else{
                    alert(resp.errmsg);
                }
            }
        });
    });

粘贴之后就完成了,修改了js文件浏览器记得清缓存

对端代码进行简单分析:

首先需要在用户进行了收藏和取消收藏后进行页面的刷新,但是不需要全部刷新,所以使用了js中的ajax来实现

局部刷新,用ajax的回调函数来执行完成后的处理。

 

posted @ 2021-10-21 21:32  和风的夏天  阅读(191)  评论(0)    收藏  举报