闲的蛋疼,索性写个东西玩,于是,写个类似于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(‘ ‘+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(‘点赞失败,可能是网络问题导致的‘) }elseif(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 isnot 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 }} </span><span>{{ article.pub_date }} </span><span>{% filter_comment article as comments %} </span><span class="glyphicon glyphicon-comment" aria-hidden="true"></span>
{{ comments.comment_count }}
<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">«</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">»</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(‘ ‘+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 postfunction(callback){
if(callback==‘error‘){
alert(‘点赞失败,可能是网络问题导致的‘)
}elseif(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!!
原文:http://www.cnblogs.com/liaojiafa/p/5638767.html
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!