zoukankan      html  css  js  c++  java
  • (二十)首页内容详细【详细页】+ 评论 + 回复

    1. 首页点瀑布流中的一个 进入详细页
      在详细页的
    onLoad里向后端发送请求
    
    2. 后端api

    一 详细页面的展示 

    1. onLoad

    // 在首页页面的代码
    <navigator url="/pages/newsDetail/newsDetail?newsId={{item.id}}"><image class="img" src="{{item.cover}}" mode="widthFix"></image></navigator>
    // 详细页
    Pages({
      /**
       * 页面的初始数据
       */
      data: {
        news:{}
      },
    
      /**
       * 生命周期函数--监听页面加载
       * 
       * 获取页面详细内容
       */
      onLoad: function (options) {
        var newsId = options.newsId
        console.log(newsId)
        wx.request({
        //自己写的url url: api.Newsdetail
    + newsId + '/', method: 'GET', dataType: 'json', responseType: 'text', success: (res)=> { if (res.statusCode===200){ this.setData({ news:res.data }) } }, }) }, })

    2. 后端API

    url(r'^newsdetail/(?P<pk>d+)/$', news.NewsViewDetail.as_view()),

    view.py

    class NewsModelViewDetail(serializers.ModelSerializer):
        user = serializers.SerializerMethodField()
        topic = serializers.SerializerMethodField()
      
      # 整合我们要的字段的格式 create_date
    = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S') images = serializers.SerializerMethodField() viewer = serializers.SerializerMethodField() comment = serializers.SerializerMethodField() class Meta: model = models.News exclude = ['cover', ] def get_user(self, obj): return model_to_dict(obj.user, fields=['id', 'nickname', 'avatar']) def get_topic(self, obj): if not obj.topic: return return model_to_dict(obj.topic, fields=['id', 'title']) def get_images(self, obj): detail_queryset = models.NewsDetail.objects.filter(news=obj) # return [{'id':item.id,'path':item.cos_path} for item in detail_queryset] # return [item.cos_path for item in detail_queryset] return [model_to_dict(item, fields=['id', 'cos_path']) for item in detail_queryset] def get_viewer(self, obj): ''''要统计浏览人的总个数 你可以自己一个一个加到数据库,也可以像下面没有注释的方法''' # 根据动态的对象 obj(news) # viewer_query = models.ViewerRecord.objects.filter(news=obj).order_by("-id")[0:10] # return [model_to_dict(item.user, fields=['nickname', 'avatar']) for item in viewer_query] queryset = models.ViewerRecord.objects.filter(news=obj) viewer_list = queryset.order_by('-id')[0:10] context = { 'count': queryset.count(), 'result': [model_to_dict(item.user, fields=['nickname', 'avatar']) for item in viewer_list] } return context def get_comment(self, obj): ''' 获取评论的第一条评论,在获取每个评论的第一条的二级评论【也就是展示一条第一级评论在展示一条对一级评论的评论】 :param obj: :return: ''' # 1.首先获取所有的一级评论 下面可以用model_to_dict 也可以直接取 value first_queryset = models.CommentRecord.objects.filter(news=obj, depth=1).order_by('-id').values( 'id', 'content', 'depth', 'user__nickname', 'user__avatar', 'create_date' ) # 2. 获取二级评论的所有评论 ''' second_queryset = models.CommentRecord.objects.filter(news=obj, depth=2).order_by('-id').values( 'id', 'content', 'user__nickname', 'user__avatar', 'create_date' ) # 2. 获取一级评论下的 二级评论 # first_id_list = [item['id'] for item in first_queryset] # second_queryset = models.CommentRecord.objects.filter(news=obj, depth=2, reply_id__in=first_id_list).order_by('-id').values('id','content','user__nickname','user__avatar','create_date') ''' # 2. 获取一级评论下的 二级评论(每个二级评论只取最新的一条) # 获取一级评论的 id first_id_list = [item['id'] for item in first_queryset] from django.db.models import Max # 到 values处 就是先取出一级评论下的所有二级评论,在取一个最大的 就是分组取最大 result = models.CommentRecord.objects.filter(news=obj, depth=2, reply_id__in=first_id_list).values( 'reply_id').annotate(max_id=Max('id')) second_id_list = [item['max_id'] for item in result] # 获取二级评论 second_queryset = models.CommentRecord.objects.filter(id__in=second_id_list).values( 'id', 'content', 'depth', 'user__nickname', 'user__avatar', 'create_date', 'reply_id', 'reply__user__nickname' ) '''这个时候我们把第一级评论和第二级评论合并 请看脚本 处理评论结构化 1. 字典的有序 2. 看下面代码 ''' import collections first_dict = collections.OrderedDict() first_dict = {} for item in first_queryset: item['create_date'] = item['create_date'].strftime('%Y-%m-%d %H:%M:%S') first_dict[item['id']] = item for node in second_queryset: node['create_date'] = node['create_date'].strftime('%Y-%m-%d %H:%M:%S') first_dict[node['reply_id']]['child'] = [node, ] return first_dict.values() # ① RetrieveAPIView 会自动查出数据库的内容 然后在走我们自定义的序列化 class NewsViewDetail(RetrieveAPIView): queryset = models.News.objects serializer_class = NewsModelViewDetail

    然后拿到数据之后我们在前端页面展示就可以啦  这里我不在赘述,后面还会有

    二 评论

    上面是每一条一级评论展示一条二级评论 但是我们要看到很多的评论的话 我们就写一个下面的代码

    #                                传过去一级评论的id           一级评论的索引 目的是要替换索引位置的值
    <text class="click_more" bindtap="click_more_content" data-root="{{item.id}}" data-parent_id='{{parent_id}}'>点击查看更多</text>
    # 获取二级评论的所有值
    url(r'^comment/$', comment.CommentView.as_view()),
    ######################################################################
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.generics import ListAPIView
    from rest_framework import serializers
    from django.forms import model_to_dict
    from app01 import models


    '''
    # 最开始用的这种方式 但是出来的字段和最开始不一样,所以用下面的方式
    class CommenModelSerializert(serializers.ModelSerializer):
    create_date = serializers.DateTimeField('%Y-%m-%d')
    user = serializers.SerializerMethodField()
    reply_user = serializers.SerializerMethodField()

    class Meta:
    model = models.CommentRecord
    fields = '__all__'

    def get_user(self, obj):
    return model_to_dict(obj.user, fields=['id', 'nickname', 'avatar'])

    def get_reply_user(self, obj):
    return model_to_dict(obj.reply.user, fields=['id', 'nickname'])

    '''
    class CommenModelSerializert(serializers.ModelSerializer):
    create_date = serializers.DateTimeField('%Y-%m-%d')
    user__nickname = serializers.CharField(source='user.nickname')
    user__avatar = serializers.CharField(source='user.avatar')
    reply_id = serializers.CharField(source='reply.id')
    reply__user__nickname = serializers.CharField(source='reply.user.nickname')

    class Meta:
    model = models.CommentRecord
    # fields = '__all__'
    exclude = ['news', 'user', 'reply', 'root']

    # 第一步 先看这
    class CommentView(APIView):
    def get(self, request, *args, **kwargs):
    root_id = request.query_params.get('root_id')
    comment_query = models.CommentRecord.objects.filter(root_id=root_id).order_by('id')

    ser = CommenModelSerializert(instance=comment_query, many=True)

    return Response(ser.data)
     
      /**
       * 点击获取更多二级评论
       */
      click_more_content:function(res){
        var root_id = res.currentTarget.dataset.root;
        var parent_id = res.currentTarget.dataset.parent_id;
    
        wx.request({
          url: api.CommentAPI,
          data: {
          root_id:root_id
          },
          method: 'GET',
          dataType: 'json',
          responseType: 'text',
          success: (res) => {
            this.setData({
          // 找到所在的位置,然后替换 [
    'news.comment['+ parent_id +'].child']:res.data }) }, }) },

    三 回复

     前端

     <view class="comment">
        <view>全部评论 - {{news.comment.length}} </view>
        <view class="tree">
          <view class="item" wx:for="{{news.comment}}" wx:key="id" wx:for-index="parent_id">
            <image class="big-avatar" src="{{item.user__avatar}}"></image>
            <view class="body">
              <view class="user">
    
                <view class="name">
                  <text>{{item.user__nickname}}</text>
                  <text>{{item.create_date}}</text>
                </view>
    
                <view class="func">
                  <text 
                  data-news="{{news.id}}" 
                  data-reply="{{item.id}}" 
                  data-depth="{{item.depth + 1}}" 
                  data-nickname="{{item.user__nickname}}"
                  data-root="{{item.id}}" 
                  bindtap="onClickShowCommentModal">回复</text>
    
                  <text wx:if="{{item.favor}}" class="red">赞</text>
    
                  <text wx:else>赞</text>
                </view>
              </view>
              <!-- 一级评论内容 -->
              <view class="content">
                ## {{item.content}}
              </view>
              <!-- 二级评论内容 -->
              <view class="reply" wx:if="{{item.child}}">
                <view class="row" wx:for="{{item.child}}" wx:key="id" wx:for-item="row">
                  <view class="reply-menu">
                    <view class="reply-user">
                      <image class="small-avatar" src="{{row.user__avatar}}"></image>
                      <view class="reply-name">
                        <text>#{{row.user__nickname}}</text>
                        <text>{{row.create_date}}</text>
                      </view>
                    </view>
                    <view class="reply-func">
                    // 文章的id 回复的id 深度 +1 头像 根id
                      <text 
                      data-news="{{news.id}}" 
                      data-reply="{{row.id}}" 
                      data-depth="{{row.depth + 1}}" 
                      data-nickname="{{row.nickname}}" 
                      data-root="{{item.id}}"
                      bindtap="onClickShowCommentModal">回复</text>
    
                      <text wx:if="{{row.favor}}" class="red">赞</text>
                      <text wx:else>赞</text>
                    </view>
                  </view>
                  <view class="reply-content">{{row.content}}</view>
    
                  <text class="click_more" 
                  bindtap="click_more_content" 
                  data-root="{{item.id}}" 
                  data-parent_id='{{parent_id}}'>点击查看更多</text>
                </view>
              </view>
            </view>
          </view>
        </view>
      </view>
    </view>
    
    <!-- 回复 -->
    <view class="buttom-view">
      <view class="comment-area" wx:if="{{isShowCommentModal}}">
        <view class="top">
          <image class="big-avatar" src="{{news.user.avatar}}"></image>
          <text>评论</text>
          <!-- 回复一级评论显示一级评论的名字 点击回复按钮显示 -->
          <view class="reply" wx:if="{{reply.reply}}">回复 {{reply.nickname}}
            <icon type="clear" size="15" bindtap="onClickClearReply"></icon>
          </view>
        </view>
        <textarea fixed="true" placeholder="评论内容..." bindinput="inputComment"></textarea>
        <view class="btn">
          <view class="publish" bindtap="onClickPostComment">发布</view>
        </view>
    
         <!-- 关闭说点什么 -->
        <view class="hide">
          <icon type="cancel" size="30" bindtap="onClickCancelCommentModal"></icon>
        </view>
      </view>
      <!-- 说点什么 -->
      <view class="text-input" wx:else>
        <image class="big-avatar" src="/static/girl.jpg"></image>
        <input placeholder="说点什么..." bindtap="onClickShowCommentModal" data-news="{{news.id}}" data-depth="{{1}}"></input>
      </view>
      <!-- 最开头的view -->
    </view>
    
                        
    前端页面
    // pages/newsDetail/newsDetail.js
    var api = require('../../config/api.js')
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        news:{},
        isShowCommentModal:false,
        reply:{}
      },
    
      /**
       * 生命周期函数--监听页面加载
       * 
       * 获取页面详细内容
       */
      getNewsDetail(newsid){
        wx.request({
          url: api.Newsdetail + newsid + '/',
          method: 'GET',
          dataType: 'json',
          responseType: 'text',
          success: (res) => {
            console.log('第28行', res.data)
            if (res.statusCode === 200) {
              this.setData({
                news: res.data
              })
            }
          },
        })
      },
      onLoad: function (options) {
        var newsid = options.newsId;
        this.getNewsDetail(newsid);
      },
      /**
       * 点击获取更多二级评论
       */
      click_more_content:function(res){
        var root_id = res.currentTarget.dataset.root;
        var parent_id = res.currentTarget.dataset.parent_id;
        wx.request({
          url: api.CommentAPI,
          data: {
          root_id:root_id
          },
          method: 'GET',
          dataType: 'json',
          responseType: 'text',
          success: (res) => {
            console.log('52',res.data)
            this.setData({
              ['news.comment['+ parent_id +'].child']:res.data
            })
          },
        })
      },
      /**
       * 点击获取输入框 
       */
      onClickShowCommentModal:function(e){
        // {depth: 1, news: 40}
        // {depth: 2, news: 40, nickname: "晓强2", reply: 21, root: 21}
        console.log(e)
        console.log('65',e.currentTarget.dataset)
        this.setData({
          isShowCommentModal:true,
          // 回复一级评论显示一级评论的名字
          reply: e.currentTarget.dataset
        })
        // 自己写的时候有bug 重新获取一下
        var news_id = e.currentTarget.dataset.news
        this.getNewsDetail(news_id)
      },
      /**
      * 点击关闭输入框 
      */
      onClickCancelCommentModal: function () {
        this.setData({
          isShowCommentModal: false
        })
      },
      /**
       * 填写评论内容
       */
      inputComment:function(e){
        // console.log(e.detail.value)
        this.setData({
          ["reply.content"]:e.detail.value
        })
      },
      /**
       * 发布
       */
      onClickPostComment:function(){
        if (!this.data.reply.content){
          wx.showToast({
            title: '请填写评论',
            icon: 'none',
          })
          return
        }
        wx.request({
          url: api.CommentAPI,
          data: {
            depth:this.data.reply.depth,
            news: this.data.reply.news,       // 回复动态的id
            // nenicknamews: this.data.reply.nickname,
            content: this.data.reply.content,
            reply: this.data.reply.reply,
            root: this.data.reply.root,
          },
          method: 'POST',
          dataType: 'json',
          responseType: 'text',
          success: (res)=> {
            console.log('113',res.data)
            if(res.statusCode==201){
              if (this.data.reply.parent_id == undefined){
                // 如果是根评论
                var dataList = this.data.news.comment
                dataList.unshift(res.data)
                // this.data.news.comment.push()       push     加到最下面
                // this.data.news.comment.unshift()    unshift  加到最上面
                this.setData({
                  ['news.comment']: dataList,
                  ['news.comment_count']: this.data.news.comment_count + 1
                })
                this.onClickCancelCommentModal()
              }else{
                // 如果是子评论
                // 1. 根据索引获取二级评论        注意 后台数据要有一级评论要有child字段
                var childcomment = this.data.news.comment[this.data.reply.parent_id].child;
                console.log(123)
                console.log(childcomment)
                console.log(res.data)
                childcomment.unshift(res.data)
                console.log('ssssss',this.data.news)
                this.setData({
                  ['news.comment[' + this.data.reply.parent_id + '].child']: childcomment,
                  ['news.comment_count']: this.data.news.comment_count + 1
                })
                this.onClickCancelCommentModal()
              }
            }
          },
        })
      },
    
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面隐藏
       */
      onHide: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面卸载
       */
      onUnload: function () {
    
      },
    
      /**
       * 页面相关事件处理函数--监听用户下拉动作
       */
      onPullDownRefresh: function () {
    
      },
    
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom: function () {
    
      },
    
      /**
       * 用户点击右上角分享
       */
      onShareAppMessage: function () {
    
      }
    })
    前端js
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.generics import ListAPIView
    from rest_framework import serializers
    from django.forms import model_to_dict
    from app01 import models
    from rest_framework import status
    from django.db.models import F
    
    
    '''
    class CommenModelSerializert(serializers.ModelSerializer):
        create_date = serializers.DateTimeField('%Y-%m-%d')
        user = serializers.SerializerMethodField()
        reply_user = serializers.SerializerMethodField()
    
        class Meta:
            model = models.CommentRecord
            fields = '__all__'
    
        def get_user(self, obj):
            return model_to_dict(obj.user, fields=['id', 'nickname', 'avatar'])
    
        def get_reply_user(self, obj):
            return model_to_dict(obj.reply.user, fields=['id', 'nickname'])
    
    '''
    class CommenModelSerializert(serializers.ModelSerializer):
        create_date = serializers.DateTimeField('%Y-%m-%d')
        user__nickname = serializers.CharField(source='user.nickname')
        user__avatar = serializers.CharField(source='user.avatar')
        reply_id = serializers.CharField(source='reply.id')
        reply__user__nickname = serializers.CharField(source='reply.user.nickname')
    
        class Meta:
            model = models.CommentRecord
            # fields = '__all__'
            exclude = ['news', 'user', 'reply', 'root']
    
    
    
    class CreateCommenModelSerializert(serializers.ModelSerializer):
        create_date = serializers.DateTimeField('%Y-%m-%d', read_only=True)
        user__nickname = serializers.CharField(source='user.nickname', read_only=True)
        user__avatar = serializers.CharField(source='user.avatar', read_only=True)
        reply_id = serializers.CharField(source='reply.id', read_only=True)
        reply__user__nickname = serializers.CharField(source='reply.user.nickname', read_only=True)
    
        class Meta:
            model = models.CommentRecord
            # fields = '__all__'
            exclude = ['user', 'favor_count']
    
    
    
    class CommentView(APIView):
        def get(self, request, *args, **kwargs):
            root_id = request.query_params.get('root_id')
    
            comment_query = models.CommentRecord.objects.filter(root_id=root_id).order_by('id')
    
            ser = CommenModelSerializert(instance=comment_query, many=True)
    
            return Response(ser.data)
    
        def post(self, request, *args, **kwargs):
    
            # 1.进行数据校验    序列化 news/ depth/reply/content/root
            ser = CreateCommenModelSerializert(data=request.data)
            # 2.校验通过 保存数据库
            if ser.is_valid():
                # 保存到数据库
                ser.save(user_id=1)
                # 对新增的数据值进行序列化【数据格式要调整 参考上面的read_only创建的时候校验,传过去不校验】
                print(ser.data)
                new_id= ser.data.get('news')
                models.News.objects.filter(id=new_id).update(comment_count=F('comment_count')+1)
                return Response(ser.data,status=status.HTTP_201_CREATED)
            return Response(ser.errors)
            # 3.将保存到数据库的数据再返回小程序页面(小程序页面要展示)
    后端逻辑

    后续会添加  点赞文章 点赞评论 关注等

  • 相关阅读:
    从技术演变的角度看互联网后台架构
    设计模式的六大原则
    Xinetd服务的安装与配置详解
    linux route详细解读
    Linux信号处理
    Go语言的成功也预示着Rust的成功【转】
    Nginx/LVS/HAProxy负载均衡软件的优缺点详解
    C#代码覆盖率实践-vsinstr和OpenCover
    MYSQL企业常用架构与调优经验分享
    StrongLoop
  • 原文地址:https://www.cnblogs.com/a438842265/p/12471259.html
Copyright © 2011-2022 走看看