CMS知识点一
一、注册功能
- ajax上传文件
from django.shortcuts import render, HttpResponse def upload(request): """ 上传文件操作 :param request: :return: """ if request.method == "POST": # 从上传的文件数据中拿到 avatar对应的文件对象 file_obj = request.FILES.get("avatar") # 在服务端新建一个和上传文件同名的新文件 with open(file_obj.name, "wb") as f: # 从上传文件对象中一点一点读数据 for i in file_obj: # 写入服务端新建的文件 f.write(i) return HttpResponse("上传成功") return render(request, "upload.html") def upload_ajax(request): """ 使用ajax方式上传 :param request: :return: """ return render(request, "upload_ajax.html")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>上传文件</title> </head> <body> <form action="" method="post" enctype="multipart/form-data"> // 必须加 enctype="multipart/form-data" {% csrf_token %} <label> <input type="file" name="avatar"> </label> <label> <input type="submit" value="上传"> </label> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>上传文件</title> </head> <body> {% csrf_token %} <input type="file" name="avatar" class="f1"> <input type="button" class="b1" value="上传"> // 使用ajax时候不要用submit <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> $(".b1").click(function () { // 先生成一个FromData对象 var fd = new FormData(); // 将要提交的数据 fd.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); fd.append("avatar", $(".f1")[0].files[0]); $.ajax({ url: "/upload/", type: "post", data: fd, contentType: false, processData: false, success: function (res) { console.log(res) } }) }); </script> </body> </html>
- 头像预览
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>上传文件</title> </head> <body> {% csrf_token %} {#style="width: 40px; border-radius: 50% 设置图片大小并修改成圆头像#} {#accept="image/*" 只显示图片类型的文件#} <label><img src="/static/images/default.png" alt="" style="width: 40px; border-radius: 50%"> <input type="file" name="avatar" class="f1" style="display: none;" accept="image/*"> </label> <input type="button" class="b1" value="上传"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> // Ajax上传头像 $(".b1").click(function () { // 先生成一个FromData对象 var fd = new FormData(); // 将要提交的数据 fd.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); fd.append("avatar", $(".f1")[0].files[0]); $.ajax({ url: "/upload/", type: "post", data: fd, contentType: false, processData: false, success: function (res) { console.log(res) } }) }); // 预览头像 $(".f1").change(function () { // 取到用户选中的头像文件 var fileobj = this.files[0]; // 新新建一个FileReader对象, 从本地磁盘加载文件数据 var fr = new FileReader(); fr.readAsDataURL(fileobj); // 读取文件需要时间 fr.onload=function () { // 找到预览头像的img标签,把踏的src属性设置成读取的用户选中的图片 $("img").attr("src", fr.result) } }); </script> </body> </html>
- Django项目上传文件之后怎么查看
1. 配置上传的文件保存在哪里 settings.py中 MEDIA_ROOT = os.path.join(BASE_DIR, "media") 上传文件需要注意两点: 1. 前端使用form表单上传需要配置 enctype="multipart/form-data" <form class="form-horizontal" action="" method="post" novalidate enctype="multipart/form-data"> 2. 后端接收 avatar_obj = request.FILES.get("avatar") 2. 如何查看上传的文件 /media/xx/oo.jpg 1. settings.py中设置 MEDIA_URL="/media/"(别名) 2. urls.py中设置 media开头的路径用什么视图函数处理 url(r'^media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}),
二、CMS表结构设计
from django.db import models from django.contrib.auth.models import AbstractUser # Create your models here. class UserInfo(AbstractUser): """ 用户表, 新增手机号字段 新增头像字段 verbose_name 在admin中显示的字段名称 """ phone = models.CharField(max_length=11, verbose_name="手机号") avatar = models.FileField(upload_to="avatars", default="avatars/default.png", verbose_name="头像") class Meta: """ verbose_name 在admin中显示的表名称 """ verbose_name = "用户管理" verbose_name_plural = verbose_name class Fault(models.Model): """ 故障表 """ title = models.CharField(max_length=50, verbose_name="故障标题") summary = models.TextField(max_length=100, verbose_name="故障概述") create_time = models.DateTimeField(auto_now_add=True, verbose_name="发布时间") modify_time = models.DateTimeField(auto_now=True, verbose_name="最后修改时间") tags = models.ManyToManyField(to="Tag", through="Fault2Tag", # 指定第三张关系表 through_fields=("fault", "tag"), # 通过哪些字段建立多对多关系 verbose_name="标签") classify = models.ForeignKey(to="Classify", verbose_name="分类", null=True) user = models.ForeignKey(to="UserInfo", verbose_name="发布用户") comment_count = models.IntegerField(default=0, verbose_name="评论总数") up_count = models.IntegerField(default=0, verbose_name="点赞总数") down_count = models.IntegerField(default=0, verbose_name="反正总数") def __str__(self): return self.title class Meta: verbose_name = "故障管理" verbose_name_plural = verbose_name class Tag(models.Model): """ 标签表 """ name = models.CharField(max_length=30, verbose_name="标签名称", unique=True) def __str__(self): return self.name class Meta: verbose_name = "标签管理" verbose_name_plural = verbose_name class Classify(models.Model): """ 分类表 """ name = models.CharField(max_length=30, verbose_name="业务线名称", unique=True) def __str__(self): return self.name class Meta: verbose_name = "业务线管理" verbose_name_plural = verbose_name class Comment(models.Model): """ 评论表 """ content = models.CharField(max_length=100, verbose_name="评论内容") comment_date = models.DateTimeField(auto_now_add=True, verbose_name="评论时间") fault = models.ForeignKey(to="Fault", verbose_name="故障总结") user = models.ForeignKey(to="UserInfo", verbose_name="评论用户") parent_comment = models.ForeignKey(to="self", null=True, blank=True, verbose_name="父级评论") # 自己关联自己,用户可以评论其他人的评论 def __str__(self): return self.content class Meta: verbose_name = "评论管理" verbose_name_plural = verbose_name class UpDown(models.Model): """ 点赞表 同一个用户只能对一篇文章进行点赞或者反对,如果点赞了就不能反对,二选一 """ user = models.ForeignKey(to="UserInfo", verbose_name="用户") fault = models.ForeignKey(to="Fault", verbose_name="故障总结") is_up = models.BooleanField(default=True, verbose_name="支持/反对") def __str__(self): return "{}-{}-{}".format(self.user.username, self.fault.title, "支持" if self.is_up else "反对") class Meta: """ unique_together联合唯一,限制一用户只能对一篇文章进行点赞或者反对 """ unique_together = (("user", "fault"),) verbose_name = "支持/反对" verbose_name_plural = verbose_name class Fault2Tag(models.Model): """ 故障报告和标签多对多关联表 手动生产第三张表,可以在第三张表增加新的字段 """ fault = models.ForeignKey(to="Fault", verbose_name="故障总结") tag = models.ForeignKey(to="Tag", verbose_name="标签名称") def __str__(self): return "{}-{}".format(self.fault.title, self.tag.name) class Meta: unique_together = (("fault", "tag"),) verbose_name = "故障-标签" verbose_name_plural = verbose_name class FaultDetail(models.Model): """ 故障内容表 为什么不和故障表放到一起? 故障内容可能多,用户每次请求页面的时候都请求故障内容,就会很慢。 """ content = models.TextField(verbose_name="故障内容") fault = models.ForeignKey(to="Fault", verbose_name="故障总结") def __str__(self): return self.content class Meta: verbose_name = "故障详情" verbose_name_plural = verbose_name
三、CMS首页和个人中心页面实现
ORM 高阶用法都在 --> https://www.cnblogs.com/liwenzhou/p/8660826.html 1. ORM分组和聚合查询 聚合内置函数:from django.db.models import Avg, Sum, Max, Min, Count annotate() annotate()前面查的是什么就按照什么分组 .values("dept").annotate()就表示按照dept分组 2. 时间格式化函数 1. MySQL DATE_FORMAT(字段, '格式') 示例:models.Fault.objects.all().extra(select={"ym": "date_format(create_time, '%%Y-%%m')"}).values("ym").annotate(num=Count("id")).values("ym", "num") 2. sqlite strftime('格式', 字段) 示例:models.Fault.objects.all().extra(select={"ym": "strftime('%%Y-%%m', create_time)"}).values("ym").annotate(num=Count("id")).values("ym", "num")
3. Django ORM执行原生SQL语句 1. 使用extra()执行部分sql语句 示例:models.Fault.objects.all().extra(select={"ym": "date_format(create_time, '%%Y-%%m')"}).values("ym").annotate(num=Count("id")).values("ym", "num") 2. 类似pymysql执行方式
4. 二级路由 1. 保障系统4合1 代码示例: CMS urls.py: from fault_reporting import urls as fault_urls urlpatterns = [ url(r'^fault-report/', include(fault_urls)) ] fault_reporting urls.py: urlpatterns = [ # 根据产品线,标签,日期归档分类 ()在正则是分组的意思,这里分2个组传了2个参数 url(r'(class|tag|archive)/(.*)/$', views.index) ]