BBS仿博客园代码总结2---首页导航条搭建、改密码、注销登录、admin后台管理、后台数据绑定、主页面文章内容区页面搭建、media媒体目录
首页导航条相关代码
整体思路就是先把主页的导航条搭好,利用模态框作为修改密码的的页面,
提交修改密码数据的按钮弄一个点击事件,获取模态框里面的老密码,新密码,确认密码,利用ajax将数据发给后端的该密码视图函数
if request.user.check_password(old_pwd):
# 再校验两次密码是否一致,以及两次密码不能为空
if new_pwd == confirm_pwd and new_pwd:
request.user.set_password(new_pwd) # 修改密码
request.user.save() # 保存密码
------------------------------
然后把小逻辑补一下,修改密码视图函数就结束了
------------------------------
auth.logout(request)
return redirect('/home/')
# 注销登录就两行代码
------------------------------
.
.
# 网站首页
path('home/', views.home_func, name='home_view'),
---------------------------------------------
def home_func(request):
# 查询所有用户编写的文章
article_queryset = models.Article.objects.all()
# 分页器
from app01 import mypage
page_obj = mypage.Pagination(current_page=request.GET.get('page'), all_count=article_queryset.count())
part_queryset = article_queryset[page_obj.start:page_obj.end]
return render(request, 'homePage.html', locals())
---------------------------------------------
.
.
home页面的html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/jQuery3.6.js"></script>
<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>
</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>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="搜索">
</div>
<button type="submit" class="btn btn-default">搜索</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">
<!--data-toggle与data-target是用来触发模态框弹出的 -->
<li><a href="#" data-toggle="modal" data-target="#myModal">修改密码</a></li>
<li><a href="#">修改头像</a></li>
<li><a href="#">后台管理</a></li>
<li role="separator" class="divider"></li>
<li><a href="/app01/logout/">注销登录</a></li>
</ul>
</li>
{% else %}
<li><a href="{% url 'register_view' %}">注册</a></li>
<li><a href="{% url 'login_view' %}">登录</a></li>
{% endif %}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<!--导航条结束-->
<!--模态框开始-->
<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 text-center" id="myModalLabel">修改密码</h4>
</div>
<div class="modal-body">
<!--这块自己写的!!!-->
<div class="form-group">
<label for="">用户名</label>
<input type="text" value="{{ request.user.username }}" disabled class="form-control">
</div>
<div class="form-group">
<label for="">原密码</label>
<input type="text" id="old_pwd" class="form-control">
</div>
<div class="form-group">
<label for="">新密码</label>
<input type="text" id="new_pwd" class="form-control">
</div>
<div class="form-group">
<label for="">确认密码</label>
<input type="text" id="confirm_pwd" class="form-control">
</div>
</div>
<div class="modal-footer">
<span id="error" style="color: red"></span>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-warning" id="setBtn">修改</button>
</div>
</div>
</div>
</div>
<!--模态框结束-->
<script>
$('#setBtn').click(function () {
$.ajax({
url: '/app01/set_pwd/',
type: 'post',
data: {
'old_pwd': $('#old_pwd').val(),
'new_pwd': $('#new_pwd').val(),
'confirm_pwd': $('#confirm_pwd').val(),
'csrfmiddlewaretoken': '{{csrf_token}}'
},
success:function (args) {
if (args.code === 10000){
window.location.href = args.url
}else{
$('#error').text(args.msg)
}
}
})
})
</script>
<!--用jquery拿用户输在标签里面的数据时,不需要像form表单一样,要input标签具有name属性才能在后端通过request.POST.get('')拿用户写在标签里面的数据-->
</body>
</html>
---------------------------------------------
.
.
.
改密码与注销登录
# 修改密码
path('set_pwd/', views.set_pwd_func),
# 注销登录
path('logout/', views.logout_func),
---------------------------------------------
# 在settings配置文件里面配一个LOGIN_URL = '/login/'
@login_required
def set_pwd_func(request):
back_dict = {'code': 10000, 'msg': ''}
if request.method == 'POST':
old_pwd = request.POST.get('old_pwd')
new_pwd = request.POST.get('new_pwd')
confirm_pwd = request.POST.get('confirm_pwd')
# 校验原密码是否正确
if request.user.check_password(old_pwd):
# 校验两次密码是否一致,以及两次密码不能为空
if new_pwd == confirm_pwd and new_pwd:
# 修改密码
request.user.set_password(new_pwd)
request.user.save()
back_dict['msg'] = '密码修改成功'
back_dict['url'] = '/app01/login/'
# auth组件会自动在你密码修改成功后,将原来登录成功的状态给注销掉
else:
back_dict['code'] = '10001'
back_dict['msg'] = '两次密码不一致或者密码为空'
else:
back_dict['code'] = '10002'
back_dict['msg'] = '原密码输入不正确'
return JsonResponse(back_dict)
-------------------------------------------
@login_required
def logout_func(request):
auth.logout(request)
return redirect('/home/')
.
.
admin后台管理
tools里面run manage.py task 在快捷命令行里面,创建超级管理员用户,进入django提供的admin后台管理里面。
要在admin.py文件里面,把想要操作的模型表在该文件里面注册一下
.
.
修改admin后台管理的表名
.
.
.
后台数据绑定
后台数据的绑定,注意用户信息表与个人站点表的绑定一定不要绑错了,因为后面我们要通过个人站点查该用户的文章,个人咱店绑错了,就会导致该个人站点下显示的都是别人的文章了,文章与个人站点表有外键联系,但是与个人信息表没有外键联系!!!
从文章表开始入手,创建站点表,标签表,分类表,文章与标签多对多的表,的表数据
点赞点踩表与评论表可以暂时不用绑数据
.
.
.
主页面文章内容区页面搭建
<!--内容区开始-->
<div class="container-fluid">
<div class="row">
<!--左广告栏-->
<div class="col-md-2">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">重金求子</h3>
</div>
<div class="panel-body">
事后必有重谢:wuyong123
</div>
</div>
</div>
<!--内容区-->
<div class="col-md-8">
<div class="text-center">{{ page_obj.page_html|safe }}</div>
{% for article_obj in part_queryset %}
<!--bootstrap媒体对象里面拿的样式代码-->
<div class="media">
<h4 class="media-heading"><a href="#">{{ article_obj.title }}</a></h4> <!--文章标题-->
<div class="media-left">
<a href="#">
<!--文章对象跨表查询拿到用户信息表里面的头像-->
<!--注意如果有路由分发,前面的路径要拼全了,漏忘了app01 ,发送请求的网站就变成了http://127.0.0.1:8099/media/avatar/3333.jpg/-->
<img class="media-object" src="/app01/media/{{ article_obj.site.userinfo.avatar }}/" alt="..." width="80">
</a>
</div>
<div class="media-body">
{{ article_obj.desc }}
<!--文章简介-->
</div>
<br>
<!--br有换行的作用,和上面标签就隔开一点了-->
<!--文章对应的用户名,时间,点赞数,点踩数,评论数-->
<!--文章对象拿用户名,先通过外键正向到个人站点表,再反向表名小写到个人信息表-->
<!--由于个人站点与个人信息是一对一的所以表名小写后面不要加_set-->
<div>
<span><a href="/{{ article_obj.site.userinfo.username }}/">{{ article_obj.site.userinfo.username }}</a></span>
<span style="margin-right: 20px">{{
article_obj.create_time|date:'Y-m-d H:i' }}</span>
<span class="glyphicon glyphicon-thumbs-up"
style="margin-right: 20px">{{ article_obj.up_num }}</span>
<span class="glyphicon glyphicon-thumbs-down"
style="margin-right: 20px">{{ article_obj.down_num }}</span>
<span class="glyphicon glyphicon-comment"
style="margin-right: 20px">{{ article_obj.comment_num }}</span>
</div>
</div>
<hr> <!--分割线-->
{% endfor %}
<!--分页器标签 page_html就是分页器类里面专门用来控制分页器标签数量与样式的函数-->
<!--注意对象别用错了,要用分页器类产生的对象去点page_html,千万别误用成for循环出来的对象-->
<div class="text-center">{{ page_obj.page_html|safe }}</div>
</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">
事后必有重谢:wuyong123
</div>
</div>
</div>
</div>
</div>
<!--内容区结束-->
.
.
.
media媒体目录
想做意见事情,用户无论上传什么东西,都固定的存到某一个目录下,在该目录下再去划分,上传的东西属于什么类型的。
需要在settings 文件里面加一句话
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
以后用户上传的静态文件会自动存到media文件目录下,但是针对用户上传的文件,我们在模型层又限制了字段数据要存到固定的比如头像字段数据存avatar目录下
那么就会变成自动在media目录下再开一个avatar目录存用户上传的头像字段数据,其他的字段的数据要存的目录也同理开在media目录下
这样以后media目录下面存储的所有用户上传的媒体文件,为什么不直接存数据库里面的表里面,因为文件类型的数据,在数据库里面都是存储的文件路径,不存文件的整体的
最后 还要到路由层写自定义暴露资源接口
# 写暴露资源接口用
from django.views.static import serve
from django.conf import settings
re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})
这样弄好后,media目录下所有的资源就都暴露出来了,只要在浏览器里面,路由先写media,后面只要路径写对了,就能访问到后端media目录下对应路径的文件资源了!!!
该方法可以支持暴露任何你想要暴露的后端文件数据,只要settings里面目录名一改,路由层的开头的路由名一改就行了,打个比方都换成app01,这样在浏览器就可以访问后端app01下面所有的文件了!!!
.
.
.
因为我们并没有开设avatar目录的访问权限
.
.
.
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY