1、models
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db import models # Create your models here. from django.contrib.auth.models import User, AbstractUser class UserInfo(AbstractUser): """ 用户信息 """ nid = models.AutoField(primary_key=True) telephone = models.CharField(max_length=11, null=True, unique=True) avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png") # auto_now_add=True ''' auto_now_add 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。 auto_now 配置上auto_now=True,每次更新数据记录的时候会更新该字段。 ''' create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE) def __str__(self): return self.username class Blog(models.Model): """ 博客信息表(站点表) """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='个人博客标题', max_length=64) site_name = models.CharField(verbose_name='站点名称', max_length=64) theme = models.CharField(verbose_name='博客主题', max_length=32) def __str__(self): return self.title class Category(models.Model): """ 博主个人文章分类表a """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='分类标题', max_length=32) blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Tag(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='标签名称', max_length=32) blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Article(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(max_length=50, verbose_name='文章标题') desc = models.CharField(max_length=255, verbose_name='文章描述') create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) content = models.TextField() # comment_count = models.IntegerField(default=0) # up_count = models.IntegerField(default=0) # down_count = models.IntegerField(default=0) user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE) tags = models.ManyToManyField( to="Tag", # 指定的是用哪个中间表 through='Article2Tag', through_fields=('article', 'tag'), ) def __str__(self): return self.title class Article2Tag(models.Model): nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid', on_delete=models.CASCADE) tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid', on_delete=models.CASCADE) class Meta: unique_together = [ ('article', 'tag'), ] def __str__(self): v = self.article.title + "---" + self.tag.title return v class ArticleUpDown(models.Model): """ 点赞表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE) article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE) is_up = models.BooleanField(default=True) class Meta: unique_together = [ ('article', 'user'), ] class Comment(models.Model): """ 评论表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE) create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) content = models.CharField(verbose_name='评论内容', max_length=255) parent_comment = models.ForeignKey("self", null=True, on_delete=models.CASCADE) def __str__(self): return self.content
2、views
from django.shortcuts import render,HttpResponse # Create your views here. from django.contrib import auth def login(request): back_message = {'user':None,'msg':None} if request.is_ajax(): name=request.POST.get('name') pwd=request.POST.get('pwd') code=request.POST.get('code') if code.upper()== request.session['code'].upper(): user=auth.authenticate(request,username=name,password=pwd) if user:
back_message['user'] = name return JsonResponse(back_message) 后面类推 else: return HttpResponse('用户名或密码错误') else: return HttpResponse('验证码错误') return render(request,'login.html') def get_random_color(): import random return (random.randint(0,255),random.randint(0,255),random.randint(0,255)) def get_code(request): import random # with open('static/img/lhf.jpg','rb') as f: # data=f.read() # pip3 install pillow 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 print("valid_code_str", valid_code_str) f = BytesIO() img.save(f, "png") data = f.getvalue() request.session['code']=valid_code_str return HttpResponse(data)
3、readme
需求 1 登录功能:基于ajax实现登录功能,生成图片验证码 2 注册功能:基于ajax和form组件实现 3 仿博客园系统首页 4 个人站点实现 5 后台管理页面 6 发布文章功能 7 基于bs4 处理xss攻击 8 文章详情页 9 文章评论,支持子评论 10 文章的点赞和反对 11 发送邮件功能 设计程序:(设计数据库表结构和关系) UserInfo:用户信息 Blog:个人站点 Article:文章表 Category:文章分类表 Tag:标签表 Article2Tag:文章标签中间表 ArticleUpDown:文章点赞表 Comment:评论表 id user_id aritcleid comment parent_id 1 用户1 给文章 11 评论了 22 null 2 用户2 给文章 11 评论了 33 null 3 用户3 给文章11 评论了44 1 4 用户4 给文章11 评论了55 3 22 -44 -55
4、urls
from django.conf.urls import url from django.contrib import admin from mybbs import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), url(r'^get_code/', views.get_code), ]
5、login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <script src="/static/jquery-3.3.1.js"></script> <title>登录页面</title> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1>登录</h1> <form> {% csrf_token %} <div class="form-group"> <label for="">用户名</label> <input type="text" id="id_name" class="form-control"> </div> <div class="form-group"> <label for="">密码</label> <input type="text" id="id_pwd" class="form-control"> </div> <div class="form-group"> <label for="">验证码</label> <div class="row"> <div class="col-lg-6"> <input type="text" id="code" class="form-control"> </div> <div class="col-lg-6"> <img height="35" width="250" src="/get_code/" alt=""> </div> </div> </div> <input type="button" id="submit" value="登录" class="btn btn-danger">
<span class='errors'></span> </form> </div> </div> </div> <script> $("#submit").click(function () { $.ajax({ url: '/login/', type: 'post', data: { 'name': $("#id_name").val(), 'pwd': $("#id_pwd").val(), 'code': $("#code").val(), 'csrfmiddlewaretoken':'{{csrf_token}}' }, success: function (data) { console.log(data) if(data.user){
location.href='/index/'}
else{
$(".errors").text(data.msg)} #可在顶端style上加css样式,变红色
} }) }) </script> </body> </html>