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>Titletitle>
<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">
<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 navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a class="navbar-brand" href="#">BBSa>
div>
<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="#">Actiona>li>
<li><a href="#">Another actiona>li>
<li><a href="#">Something else herea>li>
<li role="separator" class="divider">li>
<li><a href="#">Separated linka>li>
<li role="separator" class="divider">li>
<li><a href="#">One more separated linka>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">Submitbutton>
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>
<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>
div>
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="1024sou">a>p>
<div style="margin-top:20px">
<p style=""><b style="">404.b> 抱歉,您访问的资源不存在。p>
<p class="d">可能是网址有误,或者对应的内容被删除,或者处于私有状态。p>
<p style="color:#777;">代码改变世界,联系邮箱 contact@cnblogs.comp>
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 %}