• Web框架开发-BBS项目预备知识


    一、简介

    博客系统(cnblog) https://www.cnblogs.com/

    1.django ORM  (object relation mapping 对象关系映射)  表 = 类  对象 = 记录
    跨表查询 分组查询 annotate() 聚合查询 aggregate(*args, **kwargs)
    2.bootstrap
    3.Ajax (jquery javascript) --- javascript 去写ajax 去写写
    登录注册 点赞评论
    用框架 底层要会!
    4.用户认证系统!
      auth user

    实现功能:
    1、基于Ajax和用户认证实现登录验证
      ---- 验证码 图片 滑动(插件)
      登录 注册 Ajax

    2、基于Ajax和form组件实现注册功能

    3、系统首页的布局
      表关系第一步:
      文章表:表头 内容, 发布时间
      用户表:一对多

    4、个人站点页面设计
      标签分类 归档(发布日期group by)
      分类表:一对多 和 文章表
      标签表:多对多 和 文章表

    5、文章详细页面
      模板继承
      文章表
      
    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
    6、基于Ajax实现文章点赞与踩灭
     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')
            ]
    
    
    

     7、基于Ajax实现评论框

    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
    

      对文章的评论和对评论的评论

      评论树:

      111

        333

          555

        666

      222

      444

      评论楼:

        直接按时间下来的

      user
    id name
    1 alex
    2 egon

    id user_id artical_id create_time content p_id(记录父评论)
    1 1 2 2012 111 None
    2 2 2 2012 222 None
    3 3 2 2012 333 None
    4 4 2 2012 444 1
    5 5 2 2012 555 4
    6 6 2 2012 666 1

    create Comment():
    id = ...
    user = models.ForeignKey('User')
    artical = models.ForeignKey('Artical')
    create_time =
    content = ...
    pid = models.ForeignKey("selef",null=true,default=None) # 表的自关联

    8.kindeditor 文本编辑器
    防止跨域,安全攻击!发文章 有些<js>恶意攻击
    思路:1.转义,对文章过滤,<script></script>
    beautitulSoup 模块

    表设计:
    from django.contrib.auth.models import AbstractUser
    from django.db import models
    
    # Create your models here.
    
    
    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")
        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):    一对多
        """
        博主个人文章分类表
        """
        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):    联合唯一 UNIQUE(user_id,artical_id)
        """
        点赞表
        """
        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):   注意:对文章的评论和对评论的评论:评论树,评论楼,表的自关联(null=True)
        """
        评论表
        """
        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
    表设计模型
    
    

    二、cookie session

    1、使用

    
    
    def login(request):
            if request.method == 'POST':
                user = request.POST.get('user')
                pwd = request.POST.get('pwd')
    
                user = models.UserInfo.objects.filter(name=user,pwd=pwd).first()
                if user:
                    request.session['username'] = user.name
                    request.session['user_id'] = user.pk
                    return redirect('/index/')
                else:
                    return render(request,'login.html')
    
            return render(request,'login.html')
    
    
        def index(request):
            username = request.session.get('username')
            if not username:
                return redirect('/login/',)
            return render(request,'index.html',{'username':username})
    
    2、分析session
    django到底做了什么,其它框架没有session组件

    request.session['username'] = user.name
      1、判断session_id是否已经存在,存在就更新,不存在就创建
      2、obj.set_cookie('session_id','hn9tyjh56msytq8j4tuyffpezb9vfg09'
      3、django-session
                session-key         session-date                        expire-date
    hn9tyj*** {'username':'alex','user_id':1} 2018-06-14 04:05:28.620101

    request.session.get('username'):
    1.cookie{'session_id':'hn9tyj***'}
    2.在django-session表中:
    obj = django-session.object.filter(session-key='hn9tyj***'),first()
    obj.session-data.get('username)
    疑问:
    同一个浏览器多个用户登录:session表里不会多一个数据,除非换了浏览器;
    第二次访问,代码发生了什么事情!session表里,一个浏览器一条记录!
    每个浏览器都维持一个cookie !为什么这样?源码

    第一次浏览器访问,取不出来session_id 就创建,一条记录 create
    第二次浏览器访问,能取出来session_id,就更新,不在是创建 update
    3.查看源码
    from django.contrib.sessions.middleware import SessionMiddleware
    def process_request(self, request):pass
    def process_response(self, request, response):pass

    注意:
    1.def process_request(self, request):pass
    django 有两个settings
    用户级别 比 系统级别的高,可覆盖!

    from django.contrib.sessions.backends import db
    class SessionStore(SessionBase):pass
    request.session = self.SessionStore(session_key)

    所以:request.session 是一个空对象
    能这样赋值使因为:request.session['username'] = 'alex'
    def __getitem__(self, key):
    return self._session[key]

    def __setitem__(self, key, value):
    self._session[key] = value
    self.modified = True

    结果:得到一个request.session空对象{}
    视图函数里赋值:
    request.session['username'] = 'alex'

    2.def process_response(self, request, response):pass
    request.session.save()
    obj.save(force_insert=must_create, force_update=not must_create, using=using)
    浏览器的session_id 有,就更新,没有,就创建;

    总结:
    session源码:
    请求:http://127.0.0.1:8080/login post name=alex&pwd=123
    第一站:
    中间件SessionMiddleWare的process_request

    def process_request():
    request.session = self.SessionStore(session_key)
    _session = {}
    _session_cache = {}

    第二站:views:
    def login(request):
    user = request.POST.get('user')
    pwd = request.POST.get('pwd')

    user = models.UserInfo.objects.filter(name=user,pwd=pwd).first()
    if user:
    request.session['username'] = user.name
    request.session['user_id'] = user.pk
    return redirect('/index/')
    else:
    return render(request,'login.html')

    操作:
    执行 self.SessionStore(session_key)类下的__setitem__():
    self._session_cache = {'username':'alex','user_id',1}

    第三站:中间件 SessionMiddleware的process_response():
    存储记录:
    if self._session_key:
    self._session_key = 'asdas23213123ssasda'
    self.save(must_create=True)

    self.save(must_create=False)
    写Cookie
    response.set_cookie(
    'session_id',
    self._session_key,
    )

    看源码:理解,学习,使用!!

    4.django得流程
    浏览器 (请求首行 请求头 请求体) wsgi (http协议整理数据 解析数据) 中间件 url views orm
    中间件 process_request process_response process_view process_exception process_template_response

    wsgi 功能:1.解析请求的数据,request 之后随便用
    2.响应体 view 返回 字符串,返回浏览器 按响应格式返回,否则浏览器不识别(响应首行,响应头)
    三、用户认证组件
    from django.contrib import auth
    from django.contrib.auth.models import User

    auth
    针对 auth_user 表
    创建超级用户:
    python manage.py createsuperuser
    root root1234
    alex alex1234

    1.user = auth.authenticate(username=user, password=pwd)
    成功返回用户对象 <class 'django.contrib.auth.models.User'>
    失败返回 None

    2.auth.login(request,user)
    request.session['user_id'] = user.pk
    # request.user = user # 不能用这个 否则多个人 就串了!!
    request.user = User.objects.filter(pk=user.pk).first()

    就可以 调用
    request.user 匿名对象 / 该用户对象

    3.auth.logout(request)
    request.session.flush()

    4.from django.contrib.auth.models import User
    User.objects.create_user(username=user,password=pwd)
    User.objects.create_superuser(username=user,password=pwd,email='123@qq.com')
    权限用户 超级用户 所有表的所有权限

    示例:
    from django.shortcuts import render,HttpResponse,redirect
    from django.contrib import auth
    from django.contrib.auth.models import User
    
    def login(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            user = auth.authenticate(username = user,password=pwd)
            if user:
                auth.login(request,user)
                return redirect('/index/')
        return render(request,'login.html')
    
    def index(request):
        username = request.user.username
        if not request.user.is_authenticated:
        # if not username:
            return redirect('/login/')
        return render(request,'index.html',{'username':username})
    
    def logout(request):
        auth.logout(request)
        return redirect('/login/')
    
    def reg(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            user = User.objects.create_user(username=user,password=pwd)
            auth.login(request,user)
            return redirect('/index/')
        return render(request,'login.html')
    

     

    ?既想用 auth_user 表,还想扩展,表字段如何做呢?

    models.py
    from django.db import models
    from django.contrib.auth.models import User,AbstractUser

    # 用类继承
    # userinfo 和 auth_user 合成一张表
    # 因此可以用登录认证的功能

    class UserInfo(AbstractUser):
    tel = models.CharField(max_length=32)


    # settings配置 若没有,报错'UserInfo.groups';
    AUTH_USER_MODEL = 'app01.UserInfo'

    Tools / Run manage.py Task
    makemigrations
    migrate

    新生成得表 app01_userinfo (可以用登录认证的功能)
    字段就是 auth_user 和 UserInfo 得合成!!

     



      

     
  • 相关阅读:
    使用netty实现im聊天
    使用rabbitmq实现集群im聊天服务器消息的路由
    springcloud feign使用
    10万用户一年365天的登录情况如何用redis存储,并快速检索任意时间窗内的活跃用户
    redis的rdb与aof持久化机制
    springcloud-zinpin的安装与使用
    kafka的基本安装与使用
    RabbitMq 实现延时队列-Springboot版本
    RabbitMq 基本命令
    Dcoker 安装 rabbitMq
  • 原文地址:https://www.cnblogs.com/mike-liu/p/9703131.html
Copyright © 2020-2023  润新知