6.1 django项目-新闻博客系统之新闻详情页

06 新闻详情页

一、功能需求分析

1、功能

  • 新闻详情
  • 评论加载
  • 评论添加

二、新闻详情页

1、接口设计

  1. 接口说明

    项目项目 说明说明
    请求方法 GET
    url /news//
    参数类型 查询参数
  2. 返回结果

    新闻详情html

2、后端代码

def news_detial(request, news_id):
    if News.objects.filter(id=news_id, is_delete=False).exists():
        return render(request, 'news/news_detail.html',context={'news_id': news_id})
    else:
        return HttpResponseNotFound('

Page not found

')

3、前端html

{% extends 'base/base.html' %}
{% load static %}

{% block title %}新闻详情{% endblock %}

{% block link %}

{% endblock %}

{% block main_contain %}
      

作者 1小时前 类型
文章内容
文章评论(0)
{% if user.is_authenticated %}
{% else %} {% endif %} {% csrf_token %}
{% endblock %} {% block otherjs %} {% endblock otherjs %}

三、新闻详情

1、接口设计

  1. 接口说明

    项目项目 说明说明
    请求方法 GET
    url /news/detiallist/
    参数类型 查询参数
  2. 参数说明

    参数名 类型 是否必须 描述
    news_id 整型 新闻id
  3. 返回结果

    {
        "error": "0",
        "errmsg": "",
        "data": {
            'news_id': news_id,
            'news':{
                'title': title,
                'content': content,
                'update_time': update_time,
                'tag_name': tag_name,
                'author_username': author_username
                }
        }
    }
    

2、后端代码

def news_detial_list(request):
    try:
        news_id = int(request.GET.get('news_id', 1))
    except Exception as e:
        logger.error('新闻id错误:\n{}'.format(e))
        news_id = 1

    news = News.objects.values('title', 'content', 'update_time').annotate(
        tag_name=F('tag__name'),
        author_username=F('author__username')).filter(id=news_id, is_delete=False)

    news_list = list(news)

    if news_list:
        data = {
            'news_id': news_id,
            'news': news_list
        }

        return json_response(data=data)
    else:
        return json_response(errno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])

路由

path('news/detiallist/', views.news_detial_list, name='detial_list'),

四、评论

1、模型设计

class Comments(BaseModel):
    """
    评论模型
    """
    content = models.TextField('内容', help_text='内容')
    author = models.ForeignKey('user.User', on_delete=models.SET_NULL, null=True)
    news = models.ForeignKey('News', on_delete=models.CASCADE)

    # 本项目设计二级评论,修改Comments模型,添加一个parent字段
    parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True)

    class Meta:
        ordering = ['-update_time', '-id']  # 排序
        db_table = "tb_comments"  # 指明数据库表名
        verbose_name = "评论"  # 在admin站点中显示的名称
        verbose_name_plural = verbose_name  # 显示的复数名称

    def to_dict_data(self):
        comment_dict = {
            'news_id': self.news_id,
            'content_id': self.id,
            'content': self.content,
            'author': self.author.username,
            'update_time': self.update_time.astimezone().strftime('%Y年%m月%d日 %H:%M'),
            'parent': self.parent.to_dict_data() if self.parent else None
        }
        return comment_dict

2、接口设计

  1. 接口说明

    项目项目 说明说明
    请求方法 GET
    url /news/comments/
    参数类型 查询参数
  2. 参数说明

    参数名 类型 是否必须 描述
    news_id 整型 新闻id
  3. 返回结果

    {
        "error": "0",
        "errmsg": "",
        "data": {
            'news_id': news_id,
            'comments':{
                'id': id,
                'content': content,
                'update_time': update_time,
                'author_username': author_username,
                'parent_author_username': parent_author_username,
                'parent_content': parent_content,
                'parent_update_time': parent_update_time,
                }
        }
    }
    

3、后端代码

def comment_list(request):
    try:
        news_id = int(request.GET.get('news_id', 1))
    except Exception as e:
        logger.error('新闻id错误:\n{}'.format(e))
        news_id = 1

    comments = Comments.objects.values('id',
                'content', 'update_time',).annotate(
        author_username=F('author__username'),
        parent_author_username=F('parent__author__username'),
        parent_content=F('parent__content'),
        parent_update_time=F('parent__update_time'),
    ).filter(news_id=news_id, is_delete=False)

    # print(list(comments))

    data = {
        'news_id': news_id,
        'comments': list(comments)
    }

    return json_response(data=data)

路由

path('news/comments/', views.comment_list, name='comments_list'),

导入数据

五、添加评论

1、接口设计

1、接口说明

项目项目 说明说明
请求方法 POST
url /news//addcomments/
参数类型 查询参数

2、参数说明

参数名 类型 是否必须 描述
news_id 整数 新闻id
content 字符串 新闻评论内容
parent_id 整数 父评论id

注意:post请求需要携带csrftoken

  1. 返回结果

    {
        "error": "0",
        "errmsg": "",
        "data": {
             'news_id': news_id,
                'content_id': id,
                'content': content,
                'author': author,
                'update_time': update_time
             'parent': {
                    'news_id': news_id,
                    'content_id': id,
                    'content': content,
                    'author': author,
                    'update_time': update_time
                    'parent': null
            }
        }
    }
    
参数名 类型 是否必须 描述
news_id 整数 新闻id
content 字符串 新闻评论内容
parent_id 整数 父评论id

注意:post请求需要携带csrftoken

参数名 类型 是否必须 描述
news_id 整数 新闻id
content 字符串 新闻评论内容
parent_id 整数 父评论id

注意:post请求需要携带csrftoken

参数名 类型 是否必须 描述
news_id 整数 新闻id
content 字符串 新闻评论内容
parent_id 整数 父评论id

注意:post请求需要携带csrftoken

2、后端代码

def add_comment(request,news_id):
    if request.method == 'POST':
        # 是否登录
        if not request.user.is_authenticated:
            return json_response(errno=Code.SESSIONERR, errmsg=error_map[Code.SESSIONERR])
        form = Checkaddcomments(request.POST)
        if form.is_valid():
            # 校验成功
            # 将评论写入数据库
            # 保存到数据库
            news_id = form.cleaned_data.get('news_id')
            content = form.cleaned_data.get('content')
            parent_id = form.cleaned_data.get('parent_id')
            new_comment = Comments()
            new_comment.content = content
            new_comment.news_id = news_id
            new_comment.author = request.user
            new_comment.parent_id = parent_id if parent_id else None
            new_comment.save()

            return json_response(data=new_comment.to_dict_data())
        else:
            err_msg_str = form.get_errors()
            return json_response(errno=Code.PARAMERR, errmsg=err_msg_str)

路由

path('news//addcomments/', views.add_comment, name='addcomments'),

六、前端设计

1、前端js

/*=== newsdetialStart ===*/
$(function () {
    fn_load_newsdetial();
    console.log($('.news-contain').attr('news_id'));
    function fn_load_newsdetial() {
        let $news_id = $('.news-contain').attr('news_id');
        $
            .ajax({
                url:'/news/detiallist/?news_id=' + $news_id,
                type:'GET',
                dataType:'json'
            })
            .done((resp)=>{
                if(resp.errno === '0')
                {
                    let $news = resp.data.news[0];
                    $('.news-title').html($news.title);
                    $('.news-author').html($news.author_username);
                    $('.news-pub-time').html($news.update_time);
                    $('.news-type').html($news.tag_name);
                    $('.news-content').html($news.content);

                }
                else
                {
                    message.showError(resp.errmsg)
                }
            })
            .fail(()=>{
                message.showError('服务器超时,请重试!')
            })
    }
});
/*=== newsdetialEnd ===*/

/*=== commentsStart ===*/
$(function () {
    fn_load_comments();
    function fn_load_comments() {
        let $news_id = $('.news-contain').attr('news_id');
        $
            .ajax({
                url:'/news/comments/?news_id=' + $news_id,
                type:'GET',
                dataType:'json'
            })
            .done((resp)=>{
                if(resp.errno === '0')
                {
                    // message.showSuccess('评论获取成功');
                    resp.data.comments.forEach(function (comment) {
                        let $parent=``;
                        if(comment.parent_author_username)
                        {
                            $parent = `
${comment.parent_author_username}
${comment.parent_update_time}
${comment.parent_content}
`; } let content = `
  • avatar ${comment.author_username} ${comment.update_time}
    ${comment.content}
    ` + $parent + `回复
  • `; $('.comment-list').append(content); }) } else { message.showError(resp.errmsg) } }) .fail(()=>{ message.showError('服务器超时,请重试!') }) } }); // 修改static/js/news/news_detail.js中的代码如下 // 修改static/js/news/news_detail.js中的代码如下 $(function () { // 对评论进行评论 $('.comment-list').delegate('a,input', 'click', function () { //获取回复按钮的class属性 let sClassValue = $(this).prop('class'); // 如果点击的是回复按钮,就显示输入框 if (sClassValue.indexOf('reply_a_tag') >= 0) { $(this).next().toggle(); } // 如果点击的是取消按钮,就隐藏输入框 if (sClassValue.indexOf('reply_cancel') >= 0) { $(this).parent().toggle(); } if (sClassValue.indexOf('reply_btn') >= 0) { // 评论 let $this = $(this); let parent_id = $this.parent().attr('comment-id'); let content = $this.prev().val(); let news_id = $('.news-contain').attr('news_id'); if (!content) { message.showError('请输入评论内容!'); return } $ .ajax({ url: '/news/' + news_id + '/addcomments/', type: 'POST', data: { news_id:news_id, content: content, parent_id: parent_id }, dataType: "json" }) .done((res) => { if (res.errno === '0') { let comment = res.data; let html_comment = `
  • avatar ${comment.author}
    ${comment.content}
    ${comment.parent.author}
    ${comment.parent.update_time}
    ${comment.parent.content}
    ${comment.update_time}
    回复
  • `; message.showSuccess('评论成功!'); setTimeout(() => { $('.comment-list').prepend(html_comment); }, 800); $this.prev().val(''); // 清空输入框 $this.parent().hide(); // 关闭评论框 } else if (res.errno === '4101') { // 用户未登录 message.showError(res.errmsg); setTimeout(() => { window.location.href = '/login/' }, 800) } else { // 失败 message.showError(res.errmsg) } }) .fail(() => { message.showError('服务器超时,请重试') }) } }); // 对新闻评论 let $newsComment = $('.logged-comment input'); // 新闻评论框 let $sendComment = $('.comment-pub .comment-btn'); // 新闻评论按钮 $sendComment.click(function () { let $this = $(this); if ($this.prev().hasClass('please-login-comment')) { message.showError('未登录,请登录后再评论!'); setTimeout(() => { window.location.href = '/login/' }, 800); return } let news_id = $('.news-contain').attr('news_id'); let content = $newsComment.val(); if (!content) { message.showError('请输入评论内容!'); return } $ .ajax({ url: '/news/' + news_id + '/addcomments/', type: 'POST', data: { news_id:news_id, content: content }, dataType: 'json' }) .done((res) => { if (res.errno === '0') { let comment = res.data; let html_comment = `
  • avatar ${comment.author} ${ comment.update_time }
    ${comment.content}
    回复
  • `; message.showSuccess('评论成功!'); setTimeout(() => { $(".comment-list").prepend(html_comment); }, 800); // 清空 $newsComment.val(''); } else if (res.errno === '4101') { // 用户未登录 message.showError(res.errmsg); setTimeout(() => { window.location.href = '/user/login/' }, 800) } else { message.showError(res.errmsg); } }) .fail(() => { message.showError('服务器超时,请重试!'); }) }) });

    你可能感兴趣的:(6.1 django项目-新闻博客系统之新闻详情页)