• 将写的博客系统贴出来


      1 from django.db import models
      2 
      3 # Create your models here.
      4 
      5 
      6 from django.contrib.auth.models import AbstractUser
      7 
      8 
      9 class UserInfo(AbstractUser):
     10     """
     11     用户信息
     12     """
     13     nid = models.AutoField(primary_key=True)
     14     telephone = models.CharField(max_length=11, null=True, unique=True)
     15     avatar = models.FileField(upload_to='avatars/', default="avatars/default.png")
     16     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
     17 
     18     blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE)
     19 
     20     def __str__(self):
     21         return self.username
     22 
     23 
     24 class Blog(models.Model):
     25     """
     26     博客信息
     27     """
     28     nid = models.AutoField(primary_key=True)
     29     title = models.CharField(verbose_name='个人博客标题', max_length=64)
     30     site_name = models.CharField(verbose_name='站点名称', max_length=64)
     31     theme = models.CharField(verbose_name='博客主题', max_length=32)
     32 
     33     def __str__(self):
     34         return self.title
     35 
     36 
     37 class Category(models.Model):
     38     """
     39     博主个人文章分类表
     40     """
     41     nid = models.AutoField(primary_key=True)
     42     title = models.CharField(verbose_name='分类标题', max_length=32)
     43     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
     44 
     45     def __str__(self):
     46         return self.title
     47 
     48 
     49 class Tag(models.Model):
     50     nid = models.AutoField(primary_key=True)
     51     title = models.CharField(verbose_name='标签名称', max_length=32)
     52     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
     53 
     54     def __str__(self):
     55         return self.title
     56 
     57 
     58 class Article(models.Model):
     59     nid = models.AutoField(primary_key=True)
     60     title = models.CharField(max_length=50, verbose_name='文章标题')
     61     desc = models.CharField(max_length=255, verbose_name='文章描述')
     62     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
     63     content = models.TextField()
     64 
     65     comment_count = models.IntegerField(default=0)
     66     up_count = models.IntegerField(default=0)
     67     down_count = models.IntegerField(default=0)
     68 
     69     user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
     70     category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
     71     tags = models.ManyToManyField(
     72         to="Tag",
     73         through='Article2Tag',
     74         through_fields=('article', 'tag'),
     75     )
     76 
     77     def __str__(self):
     78         return self.title
     79 
     80 
     81 class Article2Tag(models.Model):
     82     nid = models.AutoField(primary_key=True)
     83     article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid', on_delete=models.CASCADE)
     84     tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid', on_delete=models.CASCADE)
     85 
     86     class Meta:
     87         unique_together = [
     88             ('article', 'tag'),
     89         ]
     90 
     91     def __str__(self):
     92         v = self.article.title + "---" + self.tag.title
     93         return v
     94 
     95 
     96 class ArticleUpDown(models.Model):
     97     """
     98     点赞表
     99     """
    100 
    101     nid = models.AutoField(primary_key=True)
    102     user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE)
    103     article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE)
    104     is_up = models.BooleanField(default=True)
    105 
    106     class Meta:
    107         unique_together = [
    108             ('article', 'user'),
    109         ]
    110 
    111 
    112 class Comment(models.Model):
    113     """
    114 
    115     评论表
    116 
    117     """
    118     nid = models.AutoField(primary_key=True)
    119     article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
    120     user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
    121     content = models.CharField(verbose_name='评论内容', max_length=255)
    122     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    123     parent_comment = models.ForeignKey('self', null=True, on_delete=models.CASCADE)
    124 
    125     def __str__(self):
    126         return self.content
    View Code

    上面是models的写法。

    要注意的是,因为我们使用的是自己的user_Info表所以,在settings中需要告诉django一下:

    AUTH_USER_MODEL = "blog.UserInfo"

    下图是关系表:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
    
    </head>
    <body>
    <h3>登录页面</h3>
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-lg-offset-3">
    
                <form>
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="user">用户名</label>
                        <input type="text" id="user" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="pwd">密码</label>
                        <input type="password" id="pwd" class="form-control">
                    </div>
    
    
                    <div class="form-group">
                        <label for="pwd">验证码</label>
                        <div class="row">
                            <div class="col-md-6">
                                <input type="text" class="form-control" id="valid_code">
                            </div>
                            <div class="col-md-6">
                                <img width="270" height="36" id="valid_code_img" src="/get_validCode_img/" alt="">
                            </div>
                        </div>
                    </div>
    
    
                    <input type="button" class="btn btn-default login_btn" value="submit"><span class="error"></span>
                    <a href="/register/" class="btn btn-success pull-right">注册</a>
                </form>
    
            </div>
        </div>
    </div>
    
    
    <script src="/static/js/jquery-3.2.1.min.js"></script>
    <script>
    
        // 刷新验证码
        $("#valid_code_img").click(function () {
    
            $(this)[0].src += "?"
    
        });
    
        // 登录验证
        $(".login_btn").click(function () {
    
    
            $.ajax({
                url: "",
                type: "post",
                data: {
                    user: $("#user").val(),
                    pwd: $("#pwd").val(),
                    valid_code: $("#valid_code").val(),
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
                },
                success: function (data) {
                    console.log(data);
    
                    if (data.user) {
                        if (location.search){
                            location.href = location.search.slice(6)
                        }
                        else {
                             location.href = "/index/"
                        }
    
                    }
                    else {
                        $(".error").text(data.msg).css({"color": "red", "margin-left": "10px"});
                        setTimeout(function(){
                             $(".error").text("");
                        },1000)
    
                    }
                }
            })
    
        })
    
    </script>
    </body>
    </html>
    View Code

     注意看上面的验证码刷新代码,简直奇淫技巧啊

    下面是视图函数:

    from django.shortcuts import render, HttpResponse, redirect
    from django.contrib import auth
    from blog.Myforms import UserForm
    from blog.models import UserInfo
    from blog.utils import validCode
    from blog import models
    from django.db.models import Count
    import json
    from django.http import JsonResponse
    from django.db.models import F
    from django.db import transaction
    from django.contrib.auth.decorators import login_required
    import os
    from cnblog import settings
    
    
    
    def login(request):
        """
        登录视图函数:
           get请求响应页面
           post(Ajax)请求响应字典
        :param request:
        :return:
        """
    
        if request.method == "POST":
    
            response = {"user": None, "msg": None}
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
            valid_code = request.POST.get("valid_code")
    
            valid_code_str = request.session.get("valid_code_str")
            if valid_code.upper() == valid_code_str.upper():
                user = auth.authenticate(username=user, password=pwd)
                if user:
                    auth.login(request, user)  # request.user== 当前登录对象
                    response["user"] = user.username
                else:
                    response["msg"] = "用户名或者密码错误!"
    
            else:
                response["msg"] = "验证码错误!"
    
            return JsonResponse(response)
    
        return render(request, "login.html")
    
    
    def index(request):
        """
        系统首页
        :param request:
        :return:
        """
        article_list = models.Article.objects.all()
    
        return render(request, "index.html", {"article_list": article_list})
    
    
    def logout(request):
        """
        注销视图
        :param request:
        :return:
        """
        auth.logout(request)  # request.session.flush()
    
        return redirect("/login/")
    
    
    def get_valid_code_img(request):
        """
        基于PIL模块动态生成响应状态码图片
        :param request:
        :return:
        """
        img_data = validCode.get_valid_code_img(request)
    
        return HttpResponse(img_data)
    
    
    def register(request):
        """
        注册视图函数:
           get请求响应注册页面
           post(Ajax)请求,校验字段,响应字典
        :param request:
        :return:
        """
    
        if request.is_ajax():
            print(request.POST)
            form = UserForm(request.POST)
    
            response = {"user": None, "msg": None}
            if form.is_valid():
                response["user"] = form.cleaned_data.get("user")
    
                # 生成一条用户纪录
                user = form.cleaned_data.get("user")
                print("user", user)
                pwd = form.cleaned_data.get("pwd")
                email = form.cleaned_data.get("email")
                avatar_obj = request.FILES.get("avatar")
    
                extra = {}
                if avatar_obj:
                    extra["avatar"] = avatar_obj
    
                UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra)
    
            else:
                print(form.cleaned_data)
                print(form.errors)
                response["msg"] = form.errors
    
            return JsonResponse(response)
    
        form = UserForm()
        return render(request, "register.html", {"form": form})
    
    
    def home_site(request, username, **kwargs):
        """
        个人站点视图函数
        :param request:
        :return:
        """
    
        print("kwargs", kwargs)  # 区分访问是的站点页面还是站点下的跳转页面
        print("username", username)
        user = UserInfo.objects.filter(username=username).first()
        # 判断用户是否存在!
        if not user:
            return render(request, "not_found.html")
    
        # 查询当前站点对象
    
        blog = user.blog
    
        # 1 当前用户或者当前站点对应所有文章
        # 基于对象查询
        # article_list=user.article_set.all()
        # 基于 __
    
    
        article_list = models.Article.objects.filter(user=user)
    
        if kwargs:
            condition = kwargs.get("condition")
            param = kwargs.get("param")  # 2012-12
    
            if condition == "category":
                article_list = article_list.filter(category__title=param)
            elif condition == "tag":
                article_list = article_list.filter(tags__title=param)
            else:
                year, month = param.split("/")
                article_list = article_list.filter(create_time__year=year, create_time__month=month)
    
        # 每一个后的表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段)).values("表模型的所有字段以及统计字段")
    
        # 查询每一个分类名称以及对应的文章数
    
        # ret=models.Category.objects.values("pk").annotate(c=Count("article__title")).values("title","c")
        # print(ret)
    
    
        # 查询当前站点的每一个分类名称以及对应的文章数
    
        # cate_list=models.Category.objects.filter(blog=blog).values("pk").annotate(c=Count("article__title")).values_list("title","c")
        # print(cate_list)
    
    
        # 查询当前站点的每一个标签名称以及对应的文章数
    
        # tag_list=models.Tag.objects.filter(blog=blog).values("pk").annotate(c=Count("article")).values_list("title","c")
        # print(tag_list)
    
    
        # 查询当前站点每一个年月的名称以及对应的文章数
    
        # ret=models.Article.objects.extra(select={"is_recent":"create_time > '2018-09-05'"}).values("title","is_recent")
        # print(ret)
    
        # 方式1:
        # date_list=models.Article.objects.filter(user=user).extra(select={"y_m_date":"date_format(create_time,'%%Y/%%m')"}).values("y_m_date").annotate(c=Count("nid")).values_list("y_m_date","c")
        # print(date_list)
    
    
        # 方式2:
    
        # from django.db.models.functions import TruncMonth
        #
        # ret=models.Article.objects.filter(user=user).annotate(month=TruncMonth("create_time")).values("month").annotate(c=Count("nid")).values_list("month","c")
        # print("ret----->",ret)
    
    
    
    
    
    
        return render(request, "home_site.html", {"username": username, "blog": blog, "article_list": article_list,})
    
    
    def get_classification_data(username):
        user = UserInfo.objects.filter(username=username).first()
        blog = user.blog
    
        cate_list = models.Category.objects.filter(blog=blog).values("pk").annotate(c=Count("article__title")).values_list(
            "title", "c")
    
        tag_list = models.Tag.objects.filter(blog=blog).values("pk").annotate(c=Count("article")).values_list("title", "c")
    
        date_list = models.Article.objects.filter(user=user).extra(
            select={"y_m_date": "date_format(create_time,'%%Y/%%m')"}).values("y_m_date").annotate(
            c=Count("nid")).values_list("y_m_date", "c")
    
        return {"blog": blog, "cate_list": cate_list, "date_list": date_list, "tag_list": tag_list}
    
    
    def article_detail(request, username, article_id):
        """
        文章详情页
        :param request:
        :param username:
        :param article_id:
        :return:
        """
        user = UserInfo.objects.filter(username=username).first()
        blog = user.blog
        article_obj = models.Article.objects.filter(pk=article_id).first()
    
        comment_list = models.Comment.objects.filter(article_id=article_id)
    
        return render(request, "article_detail.html", locals())
    
    
    def digg(request):
        """
        点赞功能
        :param request:
        :return:
        """
        print(request.POST)
    
        article_id = request.POST.get("article_id")
        is_up = json.loads(request.POST.get("is_up"))  # "true"
        # 点赞人即当前登录人
        user_id = request.user.pk
        obj = models.ArticleUpDown.objects.filter(user_id=user_id, article_id=article_id).first()
    
        response = {"state": True}
        if not obj:
            ard = models.ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=is_up)
    
            queryset = models.Article.objects.filter(pk=article_id)
            if is_up:
                queryset.update(up_count=F("up_count") + 1)
            else:
                queryset.update(down_count=F("down_count") + 1)
        else:
            response["state"] = False
            response["handled"] = obj.is_up
    
        return JsonResponse(response)
    
    
    def comment(request):
        """
        提交评论视图函数
        功能:
        1 保存评论
        2 创建事务
        3 发送邮件
        :param request:
        :return:
        """
        print(request.POST)
    
        article_id = request.POST.get("article_id")
        pid = request.POST.get("pid")
        content = request.POST.get("content")
        user_id = request.user.pk
    
        article_obj = models.Article.objects.filter(pk=article_id).first()
    
        # 事务操作
        with transaction.atomic():
            comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,
                                                        parent_comment_id=pid)
            models.Article.objects.filter(pk=article_id).update(comment_count=F("comment_count") + 1)
    
        response = {}
    
        response["create_time"] = comment_obj.create_time.strftime("%Y-%m-%d %X")
        response["username"] = request.user.username
        response["content"] = content
    
        # 发送邮件
    
        from django.core.mail import send_mail
        from cnblog import settings
    
        # send_mail(
        #     "您的文章%s新增了一条评论内容"%article_obj.title,
        #     content,
        #     settings.EMAIL_HOST_USER,
        #     ["916852314@qq.com"]
        # )
    
        import threading
    
        t = threading.Thread(target=send_mail, args=("您的文章%s新增了一条评论内容" % article_obj.title,
                                                     content,
                                                     settings.EMAIL_HOST_USER,
                                                     ["916852314@qq.com"])
                             )
        t.start()
    
        return JsonResponse(response)
    
    
    def get_comment_tree(request):
        article_id = request.GET.get("article_id")
        response = list(models.Comment.objects.filter(article_id=article_id).order_by("pk").values("pk", "content",
                                                                                                   "parent_comment_id"))
    
        return JsonResponse(response, safe=False)
    
    
    @login_required
    def cn_backend(request):
        """
        后台管理的首页
        :param request:
        :return:
        """
        article_list = models.Article.objects.filter(user=request.user)
    
        return render(request, "backend/backend.html", locals())
    
    
    from bs4 import BeautifulSoup
    
    
    @login_required
    def add_article(request):
        """
        后台管理的添加书籍视图函数
        :param request:
        :return:
        """
        if request.method == "POST":
            title = request.POST.get("title")
            content = request.POST.get("content")
    
            # 防止xss攻击,过滤script标签
            soup=BeautifulSoup(content,"html.parser")
            for tag in soup.find_all():
    
                print(tag.name)
                if tag.name=="script":
                    tag.decompose()
    
            # 构建摘要数据,获取标签字符串的文本前150个符号
    
            desc=soup.text[0:150]+"..."
    
            models.Article.objects.create(title=title,desc=desc,content=str(soup), user=request.user)
            return redirect("/cn_backend/")
    
        return render(request, "backend/add_article.html")
    
    
    def upload(request):
        """
        编辑器上传文件接受视图函数
        :param request:
        :return:
        """
    
        print(request.FILES)
        img_obj=request.FILES.get("upload_img")
        print(img_obj.name)
    
        path=os.path.join(settings.MEDIA_ROOT,"add_article_img",img_obj.name)
    
        with open(path,"wb") as f:
    
            for line in img_obj:
                f.write(line)
    
    
        return HttpResponse("ok")
    View Code

    ajax提交很多人会搞糊涂,就是以为ajax提交之后就可以写跳转页面,这个是不行的啊,跳转必须在前端中用location来跳转

    import random
    
    def get_random_color():
            return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
    
    
    def get_valid_code_img(request):
    
        # 方式1:
        # with open("lufei.jpg","rb") as f:
        #     data=f.read()
    
        # 方式2: # pip install pillow
    
        # from PIL import Image
        # img=Image.new("RGB",(270,40),color=get_random_color())
        #
        # with open("validCode.png","wb") as f:
        #     img.save(f,"png")
        #
        # with open("validCode.png","rb") as f:
        #     data=f.read()
    
    
        # 方式3:
    
        # from PIL import Image
        # from io import BytesIO
        #
        # img=Image.new("RGB",(270,40),color=get_random_color())
        # f=BytesIO()
        # img.save(f,"png")
        # data=f.getvalue()
    
    
    
        # 方式4:
    
        from PIL import Image, ImageDraw, ImageFont
        from io import BytesIO
        import random
    
        img = Image.new("RGB", (270, 40), color=get_random_color())
    
        draw = ImageDraw.Draw(img)
        kumo_font = ImageFont.truetype("static/font/kumo.ttf", size=32)
    
        valid_code_str = ""
        for i in range(5):
            random_num = str(random.randint(0, 9))
            random_low_alpha = chr(random.randint(95, 122))
            random_upper_alpha = chr(random.randint(65, 90))
            random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
            draw.text((i * 50 + 20, 5), random_char, get_random_color(), font=kumo_font)
    
            # 保存验证码字符串
            valid_code_str += random_char
    
        # width=270
        # height=40
        # for i in range(10):
        #     x1=random.randint(0,width)
        #     x2=random.randint(0,width)
        #     y1=random.randint(0,height)
        #     y2=random.randint(0,height)
        #     draw.line((x1,y1,x2,y2),fill=get_random_color())
        #
        # for i in range(100):
        #     draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
        #     x = random.randint(0, width)
        #     y = random.randint(0, height)
        #     draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
    
        print("valid_code_str", valid_code_str)
    
        request.session["valid_code_str"] = valid_code_str
    
        '''
        1 sdajsdq33asdasd
        2 COOKIE {"sessionid":sdajsdq33asdasd}
        3 django-session
          session-key       session-data
          sdajsdq33asdasd   {"valid_code_str":"12345"}
    
    
        '''
    
        f = BytesIO()
        img.save(f, "png")
        data = f.getvalue()
    
    
        return data
    View Code

    验证码

    当发送ajax请求的时候需要返回的是json状态的queryset怎么办?直接强转!!!

    我的博客第一节中写了,但是,一定要在JsonResponse后加一个safe=False

    为什么呢?看源码!

    那么拿到数据之后再前端就开始遍历:

     通过取反parent_comment_id判断是否为跟评论

    没有过不去的坎,只有没加够的油!
  • 相关阅读:
    JavaScript中的闭包
    正则表达式(括号)、[中括号]、{大括号}的区别
    写出将字符串中的数字转换为整型的方法,如:“as31d2v”->312,并写出相应的单元测试,正则去掉非数值、小数点及正负号外的字符串
    正则替换实现字符串链接每4位用“-”连接成新的字符串
    memcache搭建
    MySQL优化
    网络优化
    JDK配置及tomcat部署
    oracle中增加pga和sga
    sudo用法
  • 原文地址:https://www.cnblogs.com/zhoulixiansen/p/9315130.html
Copyright © 2020-2023  润新知