BBS首页搭建(包括修改密码和退出功能实现)+后台管理+media配置,用户头像展示+个人站点文章展示(图片防盗链、左边侧边栏、侧边栏筛选)
1.首页导航条
2.导航条修改密码及注册功能(修改密码,或者退出需要用户登录,需要加上登录装饰器,导入,然后全局配)
3.admin后台管理(首页搭建好了,文章还没录入,有7张表,一张一张录比较麻烦,就借助于后台管理,先创建createsuperuser)
4.media配置以及用户头像展示
5.个人站点文章展示(图片防盗链,文章展示)
urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views from django.views.static import serve from dj_BBS01 import settings urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^register/", views.register, name='reg'), url(r"^login/", views.login, name='login'), url(r"^get_code/", views.get_code, name='gc'), url(r"^home/", views.home, name='hm'), # 修改密码 url(r"^set/password/", views.set_password, name='set_pwd'), # 退出 url(r"^logout/", views.logout, name='logout'), #点赞点踩 url(r"^up_or_down/",views.up_or_down), #评论 url(r"^comment/",views.comment), #后台管理 url(r"^backend/", views.backend), #添加文章 url(r"^add/article/",views.add_article), #编辑器上传图片接口 url(r"^upload/image/",views.upload_image), #添加头像 url(r"^set/avatar/",views.set_avatar), # 暴露后端指定文件夹资源 url(r"^media/(?P<path>.*)", serve, {'document_root': settings.MEDIA_ROOT}), # url(r"app01/(?P<path>.*)",serve,{'document_root':settings.MEDIA_ROOT}) #个人站点页面搭建 url(r"^(?P<username>\w+)/$",views.site,name="site"), #侧边栏筛选功能 url(r"^(?P<username>\w+)/(?P<condition>category|tag|archive)/(?P<param>.*)/",views.site), #文章详情页 url(r"^(?P<username>\w+)/article/(?P<article_id>\d+)/",views.article_detail), ]
home.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script> </head> <body> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">BBS</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">博客<span class="sr-only">(current)</span></a></li> <li><a href="#">文章</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">更多 <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> <form class="navbar-form navbar-left"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> <ul class="nav navbar-nav navbar-right"> {% if request.user.is_authenticated %} <li><a href="#">{{ request.user.username }}</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">更多操作 <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#" data-toggle="modal" data-target="#myModal" >修改密码</a></li> <li><a href="/backend/">后台管理</a></li> <li><a href="/set/avatar/">修改头像</a></li> <li role="separator" class="divider"></li> <li><a href="{% url 'logout'%}">退出登录</a></li> </ul> <!-- Modal --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="myModalLabel" class="text-center">修改密码</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="form-group"> <label for="">用户名</label> <input type="text" class="form-control" disabled value="{{ request.user.username }}"> </div> <div class="form-group"> <label for="">原密码</label> <input type="password" id="id_old_password" class="form-control" name="old_password"> </div> <div class="form-group"> <label for="">新密码</label> <input type="password" id="id_new_password" class="form-control" name="new_password"> </div> <div class="form-group"> <label for="">确认密码</label> <input type="password" id="id_confirm_password" class="form-control" name="confirm_password"> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="id_edit">保存修改</button> <span style="color: red" id="password_error"></span> </div> </div> </div> </div> </li> {% else %} <li><a href="{% url 'reg' %}">注册</a></li> <li><a href="{% url 'login' %}">登录</a></li> {% endif %} </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <div class="container-fluid"> <div class="col-md-2"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">灵魂在高处</h3> </div> <div class="panel-body"> 清晨,如果我比往常早点去公司,总会在一个特定的时间和路段,与一位中年环卫工相遇。 </div> </div> <div class="panel panel-danger"> <div class="panel-heading"> <h3 class="panel-title">人最软弱的地方是舍不得</h3> </div> <div class="panel-body"> 人最软弱的地方是舍不得 真正的爱情,不是一见钟情,而是日久生情;真正的缘份,不是上天的安排,而是你的主动;真正的自卑 </div> </div> <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">学会低头,更能出头</h3> </div> <div class="panel-body"> 低头是一种能力,它不是自卑,也不是怯弱,它是清醒中的嬗变。 学会低头,更能出头有时,稍微低一下头,或许我们的人生路会更精彩。 懂得低头,才能出头! </div> </div> </div> <div class="col-md-8"> <ul class="media-list"> {% for article_obj in article_queryset %} <li class="media"> <h4 class="media-heading"><a href="/{{ article_obj.blog.userinfo.username }}/article/{{ article_obj.pk }}" >{{ article_obj.title}}</a></h4> <div class="media-left"> <a href="#"> <img class="media-object" src="/{{ article_obj.blog.userinfo.avatar }}" width=60 alt="..."> </a> </div> <div class="media-body"> {{ article_obj.desc }} </div> <br> <div> <span><a href="/{{ article_obj.blog.userinfo.username }}/article/{{ article_obj.pk }}">{{ article_obj.blog.userinfo.username}} </a></span> <span>发布于 </span> <span>{{ article_obj.create_time }} </span> <span><span class="glyphicon glyphicon-comment"></span>评论({{ article_obj.comment_num }}) </span> <span><span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article_obj.up_num }})</span> </div> </li> <hr> {% endfor %} </ul> </div> <div class="col-md-2"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">灵魂在高处</h3> </div> <div class="panel-body"> 清晨,如果我比往常早点去公司,总会在一个特定的时间和路段,与一位中年环卫工相遇。 </div> </div> <div class="panel panel-danger"> <div class="panel-heading"> <h3 class="panel-title">人最软弱的地方是舍不得</h3> </div> <div class="panel-body"> 人最软弱的地方是舍不得 真正的爱情,不是一见钟情,而是日久生情;真正的缘份,不是上天的安排,而是你的主动;真正的自卑 </div> </div> <div class="panel panel-info"> <div class="panel-heading"> <h3 class="panel-title">学会低头,更能出头</h3> </div> <div class="panel-body"> 低头是一种能力,它不是自卑,也不是怯弱,它是清醒中的嬗变。 学会低头,更能出头有时,稍微低一下头,或许我们的人生路会更精彩。 懂得低头,才能出头! </div> </div> </div> </div> <script> $("#id_edit").click(function(){ $.ajax({ url:'/set_password/', type:'post', data:{ "old_password":$("#id_old_password").val(), "new_password":$("#id_new_password").val(), "confirm_password":$("#id_confirm_password").val(), "csrfmiddlewaretoken":'{{ csrf_token }}' }, success:function (args) { if (args.code==1000){ {#window.location.href='home/'#} window.location.reload() {#$('#myModal').modal('hide')#} }else{ $("#password_error").text(args.msg) } } }) }) </script> </body> </html>
views.py
from django.contrib.auth.decorators import login_required
@login_required # 必须先登录才能修改密码
def set_password(request):
if request.is_ajax():
back_dic = {"code": 1000, 'msg': ""}
if request.method == "POST":
old_password = request.POST.get('old_password')
new_password = request.POST.get('new_password')
confirm_password = request.POST.get('confirm_password')
is_right = request.user.check_password(old_password)
if is_right:
if new_password == confirm_password:
request.user.set_password(new_password)
request.user.save()
back_dic['msg'] = '修改成功'
else:
back_dic['code'] = 1001
back_dic['msg'] = '两次密码并不一致'
else:
back_dic['code'] = 1002
back_dic['msg'] = '原密码错误'
return JsonResponse(back_dic)
@login_required
def logout(request):
auth.logout(request)
return redirect('/home/')
settings.py
LOGIN_URL='/login/'
media配置(复制媒体对象)
用户头像展示
#settings.py配置用户上传的文件存储位置
MEDIA_ROOT=os.path.join(BASE_DIR,"media")
# MEDIA_ROOT=os. path.join(BASE_DIR,"app01")
个人站点展示(图片防盗链)
views.py
def site(request,username,**kwargs):
"""
如果该参数有值,也就意味着需要对article_list做额外的判断
:param request:
:param username:
:param kwargs:
:return:
"""
#先校验当前用户名对应的个人站点是否存在
user_obj=models.UserInfo.objects.filter(username=username).first()
#用户如果不存在返回一个404页面
if not user_obj:
return render(request,'error.html')
blog=user_obj.blog #存在则返回个人站点页面,先拿到个人站点
#查看当前个人站点的所有文章
article_list=models.Article.objects.filter(blog=blog)
if kwargs:
condition=kwargs.get('condition')
param=kwargs.get("param")
if condition=='category':
article_list=article_list.filter(category_id=param)
elif condition=='tag':
article_list=article_list.filter(tags__id=param)
else:
year,month=param.split("-")
article_list=article_list.filter(create_time__year=year,create_time__month=month)
#查寻当前站点下所有的分类以及分类下的文章数
category_list=models.Category.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list('name','count_num','pk')
#print(category_list)
#查寻当前站点下所有的标签以及标签下的文章数
tag_list=models.Tag.objects.filter(blog=blog).annotate(count_num=Count('article__pk')).values_list("name",'count_num','pk')
#print(tag_list)
#查寻当前站点下所有的时间分类以及文章数
date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values(
'month').annotate(count_num=Count('pk')).values_list('month', 'count_num')
# print(date_list)
return render(request,'site.html',locals())
error.html(直接复制博客园页面的404)
<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <link rel="icon" href="//common.cnblogs.com/favicon.ico" type="image/x-icon" /> <title>404 页面不存在 - 博客园</title> <style type='text/css'> body { margin: 8% auto 0; max-width: 400px; min-height: 200px; padding: 10px; font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; font-size: 14px; padding-right: 200px; position: relative; } p { color: #555;margin: 15px 0px; } img { border: 0px; } .d { color: #404040; } .robot img { max-width: 192px; } .robot { position: absolute; top: 0; right: 0; } </style> </head> <body> <p style="margin-left: 5px;"><a href="https://www.cnblogs.com/"><img src="//common.cnblogs.com/logo.svg" style="height:45px" alt="cnblogs"></a></p> <div style="margin-top:20px"> <p style=""><b style="">404.</b> 抱歉,您访问的资源不存在。</p> <p class="d">可能是网址有误,或者对应的内容被删除,或者处于私有状态。</p> <p style="color:#777;">代码改变世界,联系邮箱 contact@cnblogs.com</p> </div> <div class="robot"><a href="//www.cnblogs.com/cmt/articles/13940458.html"><img src="//common.cnblogs.com/images/404-robot.png" alt="404 robot" /></a></div> <script async src="https://www.googletagmanager.com/gtag/js?id=G-4CQQXWHK3C"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-4CQQXWHK3C'); </script> </body> </html>
site.html
{% extends 'base.html' %} {% block content %} <div class="col-md-9"> <ul class="media-list"> {% for article_obj in article_list %} <li class="media"> <h4 class="media-heading"><a href="/{{ username }}/article/{{ article_obj.pk }}" >{{ article_obj.title}}</a></h4> <div class="media-left"> <a href="#"> <img class="media-object" src="/{{ article_obj.blog.userinfo.avatar }}" width=60 alt="..."> </a> </div> <div class="media-body"> {{ article_obj.desc }} </div> <div class="pull-right"> <span>posted </span> <span>@ </span> <span>{{ article_obj.create_time|date:'Y-m-d' }} </span> <span><a href="">{{ article_obj.blog.userinfo.username}} </a></span> <span><span class="glyphicon glyphicon-comment"></span>评论({{ article_obj.comment_num }}) </span> <span><span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article_obj.up_num }}) </span> <span><a href="">编辑</a></span> </div> </li> <hr> {% endfor %} </ul> </div> {% endblock %}