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 得合成!!

 



  

 
posted @ 2018-09-25 20:07  芳姐  阅读(309)  评论(0编辑  收藏  举报