python小打小闹之简陋版BBS

  闲的蛋疼,索性写个东西玩,于是,写个类似于BBS的念头就开始了。

  我们考虑到需要实现的功能:

    1 只有登陆的用户才可以点赞,如果没有登陆,那么不可以点赞,点赞次数只可以为1。

    2 只有登陆的用户可以评论文章,其他用户也可通过回复其他人的评论。

    3 评论之间有多级嵌套关系,不是单独存在的,比我评论文章A,别人在我的评论基础上再评论我的评论,那么我的评论和别人评论我的评论之间存在一层关系。

    4 用户可以增删改查自己的文章,可以搜索自己的文章。文章包含三种状态,发布,草稿,隐藏。

    5 每篇文章需要显示发布日期,发布人,点赞次数,评论次数,在首页展示的时候能够图文并茂展示,通过文章优先级来让部分文章置顶显示。

    6 文章要有归属模块,页面展示出板块

    7 and so on ...

  我个人觉得只要实现上述功能,BBS的雏形就出来了。那么开工吧。

  所需要的知识:

      1 django+python

      2 js

      3 jinja

  =================================================================================================

  首先这个毫无疑问使用的Django 作为我的web frame。

  第一要解决的是数据库关系,此时我拿Django默认的sqilite作为我的数据库,数据库关系我的想法是:

    文章表:用户名(外键关联用户表), 发布时间,修改时间,状态,文章内容,文章归属模块,内容简介,优先级,文章头像

    评论表:评论时间,是点赞还是评论,评论内容,归属哪篇文章(关键文章表),父籍评论ID

    版块表:名字,简介,置顶文章,版块位置。

    用户表: 关联Django系统自带的用户,用户名。

  数据库建表关系解决 后,那就初始化,数据库。。。。。。。。

  代码我在此我就简单说说几点:

    1 点赞次数限制:

      说到点赞,我们采用三个值来确定这个用户是否点赞过一次了,文章ID+用户ID+当前点赞次数

      我们在评论表存储这个用户点赞次数的时候,连同用户ID一块存储进去,所以我们单单过滤这个表就可以了。

      前端代码:

 <script src="/static/bootstrap/js/jquery-2.1.4.js"></script>
    <script>
        //获取点赞数的函数
        function Get_Praise(article_id,ele){
            $.get("{% url "post_comment" %}",
                    {‘id‘:article_id,‘choice‘:2}, //紧跟的是参数
                    function (data) {
                        $(ele).html(‘&nbsp;‘+data)
                    }
            )
        }
        //提交点赞请求
        function click_praise(ele){
            var article_id = $(ele).siblings().first().attr(‘article_id‘);
            var GetCsrf = $("input[name=‘csrfmiddlewaretoken‘]").val();
            // begin post
            $.post("{% url ‘post_comment‘ %}",
                    {
                        ‘comment_type‘:2,
                        ‘article‘:article_id,
                        ‘user‘:‘{{ request.user.userprofile.id }}‘,
                        ‘csrfmiddlewaretoken‘: GetCsrf,
                    }, //end post
                    function(callback){               // 如果返回来的参数是limit说明这个用户被限制点赞了,因为点赞次数超过1次了
                        if(callback==‘error‘){
                            alert(‘点赞失败,可能是网络问题导致的‘)
                        }else if(callback==‘limit‘){
                            alert(‘您已经点赞过一次了,请勿重复点赞!!‘)
                        } else{
                            Get_Praise(article_id,ele)
                        }
                    }
            )
        }

      后端代码,   

praise_obj = models.Article.objects.filter(id=article_id)
for pb in praise_obj:
        # 通过反向查询,来获取comment表里面的内容,表后面必须紧接着 _set !
        pb_obj = pb.comment_set.select_related()
        # get the praise‘s number,and count that!
        praise = pb_obj.filter(comment_type=comment_type).count()return HttpResponse(praise)

  

    2 只有可以登陆才可以评论,并且在评论框中点击登陆,登陆成功后自动跳转到刚才的页面:

      前端代码展示:

        <div class="comment-box">
            {% if request.user.is_authenticated %}
                 <textarea class="form-control" rows="3"></textarea>
                    {% csrf_token %}
                 <button type="button" style="margin-top: 10px" class="btn btn-success pull-right">评论</button>
            {% else %}
                <div class="jumbotron">
                  <h4 class="text-center"><a class="btn-link" href="{% url ‘login‘ %}?next={{ request.path }}">登录</a>后评论</h4>
                </div>
            {% endif %}

        </div>

      后端代码展示:

 if request.method == ‘POST‘:
        user = authenticate(username=request.POST.get(‘username‘),
                            password=request.POST.get(‘password‘))
        if user is not None:
            #pass authentication
            login(request,user)
            return HttpResponseRedirect(request.GET.get(‘next‘) or ‘/bbs‘)

    3 评论多级嵌套关系:

      

    4 用户新建一篇自己的文章

      前端代码如下:

 <form  class="form-horizontal"  method="post"  enctype="multipart/form-data">{% csrf_token %}
            <div class="form-group">
          // 遍历form的值。
                {% for info in article %}
                    {% if info.field.required %}
                        <label style="font-size: larger">{{ info.label }}*</label></br>
                    {% else %}
                        {{ info.label }}</br>
                    {% endif %}
                        {{info}}</br>
                {% endfor %}
            <input name="author" style="display: none;" value="{{ request.user.userprofile.id }}">
            </div>
            <div class="col-sm-11">
                <input type="submit"  class="btn btn-primary " value="Save">
               <a href="/person_zone/{{ request.user.userprofile.id }}"  class="btn btn-danger">Cancel</a>
            </div>
            </form>
{% block bottom-js %}
    <script src="/static/bootstrap/js/jquery-2.1.4.js"></script>
    <script>
        $(document).ready(function () {
            window.resizeTo(10,70)
        })
    </script>
    <script src="/static/ckeditor/ckeditor.js"></script>
    <script type="text/javascript">
    // 调用的第三方编辑器,会自动把在id_content里面替换成编辑器,而这个id_content是form里面在渲染html页面的时候自动带出来的

            CKEDITOR.replace(‘id_content‘)
    </script>
{% endblock %}

      后端代码如下:

def add_article(request):
    ‘‘‘
    除了添加文章的方法
    :param request:
    :return:
    ‘‘‘
    import datetime
    errors = None
    article_list = forms.get_form(models.Article)
    if request.method == ‘POST‘:
        article_form = forms.get_form(models.Article,request.POST,request.FILES)
        if article_form.is_valid():
            data =  article_form.cleaned_data
            data[‘author_id‘] = request.user.userprofile.id
            if data[‘status‘] == "published":
                data[‘pub_date‘] == datetime.datetime.now()

            article_obj = models.Article(**data)
            article_obj.save()
            return HttpResponseRedirect(‘/bbs/‘)

        else:
             errors = ‘输入的信息不完整或者错误,不符合格式。‘

    return render(request,‘BBS/add_article.html‘,{‘article‘:article_list,
                                                  ‘category_list‘:category_list,
                                                  ‘errors‘:errors,
                                                  ‘title_of_page‘:u‘写一篇新文章‘})

    5 改查自己的文章(删除动作忘记写了)

      前端代码:

# 其实还是调用之前新写一篇文章的的页面,我只是把内容给填充到里面去了,一举多得,哈哈。
<form  class="form-horizontal"  method="post"  enctype="multipart/form-data">{% csrf_token %}
            <div class="form-group">
          // 遍历form的值。
                {% for info in article %}
                    {% if info.field.required %}
                        <label style="font-size: larger">{{ info.label }}*</label></br>
                    {% else %}
                        {{ info.label }}</br>
                    {% endif %}
                        {{info}}</br>
                {% endfor %}
            <input name="author" style="display: none;" value="{{ request.user.userprofile.id }}">
            </div>
            <div class="col-sm-11">
                <input type="submit"  class="btn btn-primary " value="Save">
               <a href="/person_zone/{{ request.user.userprofile.id }}"  class="btn btn-danger">Cancel</a>
            </div>
            </form>
{% block bottom-js %}
    <script src="/static/bootstrap/js/jquery-2.1.4.js"></script>
    <script>
        $(document).ready(function () {
            window.resizeTo(10,70)
        })
    </script>
    <script src="/static/ckeditor/ckeditor.js"></script>
    <script type="text/javascript">
    // 调用的第三方编辑器,会自动把在id_content里面替换成编辑器,而这个id_content是form里面在渲染html页面的时候自动带出来的

            CKEDITOR.replace(‘id_content‘)
    </script>
{% endblock %}

      后端代码:

def article_modify(request,article_id):
    ‘‘‘
    更改文章/博客内容的方法
    :param request:
    :param article_id: 文章ID
    :return: 网页
    ‘‘‘
    article_id_obj = models.Article.objects.get(id=article_id)
   # get_form实际是上我form里的一个装饰器,  
    form = forms.get_form(models.Article,instance=article_id_obj)
    if request.method == ‘POST‘:
        form = forms.get_form(models.Article,request.POST,instance=article_id_obj)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(‘/person_zone/%s‘%(request.user.userprofile.id))
    return render(request,‘BBS/add_article.html‘,{‘category_list‘:category_list,
                                                  ‘title_of_page‘:u‘修改文章信息‘,
                                                  ‘article‘:form,})

    6 在首页显示文章具体详情:

      前端代码:

{% extends ‘base.html‘ %}
{% load  customer_tag %}
{% load for_bbs %}
{% block page-container %}
    <div class="">
        {% for article in article_list %}
            {% csrf_token  %}
            <div class="article-box row">
                <div class="article-head-img col-md-4">
                    <img class="article-head-img" src="/static/{{ article.head_img|truncate_url }}" >
                </div>
                <div class="article-brief col-md-8">
                    <a class="article-title" href="{% url ‘article_detail‘ article.id %}">
                        {{ article.title }}<br/>
                    </a>
                    <div class="article-brief-info">
                        <span  style="display: none;"  article_id="{{ article.id }}"></span>
                        <span>{{ article.author.name }}&nbsp;</span>
                        <span>{{ article.pub_date }} &nbsp;&nbsp;</span>
                        <span>{%  filter_comment article as comments %} </span>
                        <span class="glyphicon glyphicon-comment" aria-hidden="true"></span>
                           {{ comments.comment_count }}
                        &nbsp;<a href="" style=‘text-decoration:none;‘ onclick="click_praise(this)"
                            class="glyphicon glyphicon-thumbs-up" aria-hidden="true">
                           {{ comments.thumb_count }}</a>
                    </div>
                    <div class="article-brief-text">
                        <p>{{ article.brief }}</p>
                    </div>
                </div>
            </div>
            <hr>
        {% endfor %}
    </div>
        <nav>
        <ul style="" class="pagination">
            {% if article_list.has_previous %}
                <li class=""><a href="?page={{ article_list.previous_page_number }}" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span></a></li>
            {% endif %}
                  {% for page_num in article_list.paginator.page_range %}
                      {% guess_page article_list.number page_num %}
                  {% endfor %}
            {% if article_list.has_next %}
                <li class="">
                    <a href="?page={{ article_list.next_page_number }}" aria-label="Previous">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
            {% endif %}
        </ul>

    </nav>
    <div class="wrap-right">
    </div>
    <div class="clear-both"></div>

{% endblock %}

{% block bottom-js %}
    <script src="/static/bootstrap/js/jquery-2.1.4.js"></script>
    <script>
        //获取点赞数的函数
        function Get_Praise(article_id,ele){
            $.get("{% url "post_comment" %}",
                    {‘id‘:article_id,‘choice‘:2}, //紧跟的是参数
                    function (data) {
                        $(ele).html(‘&nbsp;‘+data)
                    }
            )
        }

        //提交点赞请求
        function click_praise(ele){
            var article_id = $(ele).siblings().first().attr(‘article_id‘);
            var GetCsrf = $("input[name=‘csrfmiddlewaretoken‘]").val();
            // begin post
            $.post("{% url ‘post_comment‘ %}",
                    {
                        ‘comment_type‘:2,
                        ‘article‘:article_id,
                        ‘user‘:‘{{ request.user.userprofile.id }}‘,
                        ‘csrfmiddlewaretoken‘: GetCsrf,
                    }, //end post
                    function(callback){
                        if(callback==‘error‘){
                            alert(‘点赞失败,可能是网络问题导致的‘)
                        }else if(callback==‘limit‘){
                            alert(‘您已经点赞过一次了,请勿重复点赞!!‘)
                        } else{
                            Get_Praise(article_id,ele)
                        }
                    }
            )
        }
    </script>
{% endblock %}

      后端代码:

def category(request,category_id=4):
    ‘‘‘
    展示页面顶部模块的名字.
    :param request:
    :param category_id:
    :return:
    ‘‘‘
    category_obj = models.Category.objects.get(id=category_id)
    if category_obj.position_index == 1: # 1 表示是首页
        article_list = models.Article.objects.filter(status=‘published‘)
    else:
        article_list = models.Article.objects.filter(category_id=category_obj.id,status=‘published‘)

    article_list = paginate(request,article_list)   # 分页方法处理下,使其返回前台是分页的!
    return render(request,‘bbs/index.html‘,{‘category_list‘:category_list,
                                            ‘category_obj‘:category_obj,
                                            ‘article_list‘:article_list})

  好了,上面的代码差不多就实现了基础的功能,具体的代码细节,可以看本人的github,哈哈,as newber , you can pratice python+Django+js+jinja to by make BBS!!

时间: 2024-10-12 04:19:14

python小打小闹之简陋版BBS的相关文章

Python写的简陋版一对一聊天工具,全双工

好该睡觉了,明天还要上班~~~直接上代码,后面再总结 1 import threading 2 import os 3 import socket 4 5 6 def RecvProcess ( UDP_Socket, LocalAddrInfo ): 7 print 'UDP Recver is UP' 8 while 1: 9 data, PeerAddr = UDP_Socket.recvfrom ( 1024 ) 10 if data == 'local exit' and LocalA

目前比较流行的Python科学计算发行版

经常有身边的学友问到用什么Python发行版比较好? 其实目前比较流行的Python科学计算发行版,主要有这么几个: Python(x,y) GUI基于PyQt,曾经是功能最全也是最强大的,而且是Windows系统中科学免费Python发行版的不二选择.不过今时已不同往昔! PythonXY里面的许多包为了兼容性的问题,无法使用最新的程序包.尤其是令人气愤的是MinGW到现在还是古董级的4.5版本,而TDM-GCC现在都4.8.1-3了.不过这个包在你安装了之后,除了占用较大的磁盘空间之外,基本

python核心编程第二版

初学Python这是一本有关Python开发的指南涵盖近期发布的Pyttlon版本的核心功能特性,而不仅仅是语法学习更多的高阶内容,如正则表达式.网络.多线程.图形用户界面.Web/CGl和Python扩展等包括几个全新的章节,关于数据库.网络客户端.Java/Jytt30n和Microsoft Office等 展示数以百计的代码片段.交互实例和大量加强您的Python技能的实用练习"对Wesley Chun<Python核心编程>第二版的漫长等待是值得的--它的深邃.它的全面,以及

零基础学python》(第二版)

---恢复内容开始--- 零基础学python>(第二版) python学习手册 可以离线下载,  .chn格式, 插入小幽默笑话,在学习累的时候看看笑话 放松一下 欢迎下载转载,请注明出处,谢谢 下载地址          http://files.cnblogs.com/files/xuchunlin/%E3%80%8A%E9%9B%B6%E5%9F%BA%E7%A1%80%E5%AD%A6python%E3%80%8B%EF%BC%88%E7%AC%AC%E4%BA%8C%E7%89%88

分享《利用Python进行数据分析(第二版)》高清中文版PDF+高清英文版PDF+源代码

资料下载:https://pan.baidu.com/s/1K3DjJ9S1S3AxpacEElNF9Q <利用Python进行数据分析(第二版)>[中文版和英文版][高清完整版PDF]+[配套源代码]<利用Python进行数据分析(第二版)>中文和英文两版对比学习, 高清完整版PDF,带书签,可复制粘贴:还有配套源代码:讲解详细并配有源代码. 其中,高清中文版如图: 原文地址:http://blog.51cto.com/3215120/2306885

利用Python进行数据分析(第二版)电子版书籍分享

资料下载地址: 链接:https://pan.baidu.com/s/1y1C0bJPkSn7Sv6Eq9G5_Ug 提取码:vscu <利用Python进行数据分析(第二版)>高清中文版PDF+高清英文版PDF+配套源代码 高清中文版PDF,带目录和书签,能够复制粘贴:高清英文版PDF,带目录和书签,能够复制粘贴:中英文两版可以对比学习.配套源代码:经典书籍,讲解详细:其中,高清中文版如图: 原文地址:https://www.cnblogs.com/yxxblog/p/10716700.ht

学习《Python机器学习(第2版)》中文PDF+英文PDF+代码分析+Sebastian

学习数据科学的初学者,想进一步拓展对数据科学领域的认知,推荐学习<Python机器学习(第二版)>.<Python机器学习(第二版)>将机器学习背后的基本理论与应用实践联系起来,聚焦于如何正确地提出问题.解决问题,能帮助了解如何使用Python解决数据中的关键问题. <Python机器学习(第2版)>介绍如何用Python和基于Python的机器学习软件库进行实践,对机器学习概念的必要细节进行讨论,同时对机器学习算法的工作原理.使用方法以及如何避免掉入常见的陷阱提供直观

参考《利用Python进行数据分析(第二版)》高清中文PDF+高清英文PDF+源代码

第2版针对Python 3.6进行全面修订和更新,涵盖新版的pandas.NumPy.IPython和Jupyter,并增加大量实际案例,可以帮助高效解决一系列数据分析问题. 第2版中的主要更新了Python第三方发布版Anaconda和其他所需Python包的安装指引: 更新pandas库到2017年的新版: 新增一章关于更多高级pandas工具和一些使用提示:新增statsmodels和scikit-learn的简明使用介绍. 学习参考: <利用Python进行数据分析(第二版)>高清中文

Python科学计算发行版—Anaconda

Python是一种强大的编程语言,其提供了很多用于科学计算的模块,常见的包括numpy.scipy和matplotlib.要利用Python进行科学计算,就需要一一安装所需的模块,而这些模块可能又依赖于其它的软件包或库,因而安装和使用起来相对麻烦.幸好有人专门在做这一类事情,将科学计算所需要的模块都编译好,然后打包以发行版的形式供用户使用,Anaconda就是其中一个常用的科学计算发行版. 主页: https://store.continuum.io/cshop/anaconda/ Anacon