Django项目练习(五)——用户表开发&视频表结构开发

用户相关开发,客户端表结构开发

一、用户表开发

在app里面新建一个model包,用于放数据库相关的文件,然后在里面新建一个auth的py文件。

model中的auth文件下,我们创建一个clientUser,用户表:

# coding:utf-8

import hashlib  # 用于给密码加密
from django.db import models


# 密码加密
def hash_password(password):
    if isinstance(password, str):
        password = password.encode('utf-8')
    return hashlib.md5(password).hexdigest().upper()  # hash md5加密,然后16进制,大写


class ClientUser(models.Model):

    username = models.CharField(max_length=50, null=False, unique=True)
    password = models.CharField(max_length=255, null=False)
    avatar = models.CharField(max_length=500, default='')  # 也可以用urlfield
    gender = models.CharField(max_length=10, default='')
    birthday = models.DateTimeField(null=True, blank=True, default=None)
    status = models.BooleanField(default=True, db_index=True)
    create_time = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return 'username:{} '.format(self.username)

    # django的User在使用create_user时可以自动对密码加密,但是这里不可以,需要手写一个
    @classmethod
    def add(cls, username, password, avatar='', gender='', birthday=None):
        return cls.objects.create(
            username=username,
            password=hash_password(password),
            avatar=avatar,
            gender=gender,
            birthday=birthday,
            status=True
        )

isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。

isinstance() 与 type() 区别:

type() 不会认为子类是一种父类类型,不考虑继承关系。

isinstance() 会认为子类是一种父类类型,考虑继承关系。

如果要判断两个类型是否相同推荐使用 isinstance()。

这里我们是手动对password加密的,然后我们进入调试模式,看一下加密后的密码什么样:

In [1]: from app.model.auth import hash_password

In [2]: password = hash_password('cong')

In [3]: password
Out[3]: '3DE6A8F9608DDD4BA89F97B36D7587D6'

获取user方法:

# 获取用户
    @classmethod
    def get_user(cls, username, password):
        # 因为get获取不到会抛出异常,所以这里用try catch
        try:
            user = cls.objects.get(
                username=username,
                password=hash_password(password)
            )
            return user  # 获取到了返回user
        except:
            return None  # 获取不到,返回None

这里定义classmethod是因为要获取整个表的内容,而下面的密码修改只是获取一个用户的数据,所以不需要类方法,self就可以了。

更改密码:

# 要获取老密码和新密码,验证老密码正确,才可以换成新密码
    def update_password(self, old_password, new_password):
        hash_old_password = hash_password(old_password)
        
        if hash_old_password != self.password:  # 输入的老密码不等于我们之前的密码
            return False
        
        hash_new_password = hash_password(new_password)  # 如果密码验证通过了,就把我们拿到的new_password hash一下
        self.password = hash_new_password
        self.save()  # 把新密码存上
        
        return True

用户状态变更

# 用户状态更改
    def update_status(self):
        self.status = not self.status  # 将状态取反,就是状态变更了
        self.save()
        
        return True

二、视频相关数据库开发

在model文件夹下,再创建一个video文件
视频的主表如下:

# coding:utf-8

from enum import Enum  # 在Python3 枚举是一个默认存在的包,优先级大于django,放在最上面
from django.db import models


# video的类型
class VideoType(Enum):
    movie = 'movie'
    cartoon = 'cartoon'
    episode = 'episode'
    variety = 'variety'
    other = 'other'


VideoType.movie.label = '电影'  # 给他添加标签
VideoType.cartoon.label = '动漫'
VideoType.episode.label = '剧集'
VideoType.variety.label = '综艺'
VideoType.other.label = '其他'


# 视频来源依旧用枚举的方式来定义
class FromType(Enum):
    youku = 'youku'
    custom = 'custom'


FromType.youku.label = '优酷'
FromType.custom.label = '自制'


# 定义视频国家枚举
class NationalityType(Enum):
    china = 'china'
    japan = 'japan'
    korea = 'korea'
    america = 'america'
    other = 'other'


NationalityType.china.label = '中国'
NationalityType.japan.label = '日本'
NationalityType.korea.label = '韩国'
NationalityType.america.label = '美国'
NationalityType.other.label = '其他'


# 视频的主表
class Video(models.Model):
    name = models.CharField(max_length=100, null=False)
    image = models.CharField(max_length=500, default='')  # 视频的海报图片
    video_type = models.CharField(max_length=50, default=VideoType.other.value)  # type是Python的关键字  .value就能取到后面传的值了
    from_to = models.CharField(max_length=20, null=False, default=FromType.custom.value)  # 视频来源
    nationality = models.CharField(max_length=20, default=NationalityType.other.value)
    info = models.TextField()  # 描述
    status = models.BooleanField(default=True, db_index=True)  # 视频状态 是否可用
    created_time = models.DateTimeField(auto_now_add=True)  # 只有第一次创建的时候会修改时间
    updated_time = models.DateTimeField(auto_now=True)  # 每次修改都会修改当前的时间
    
    # 联合 唯一 索引  多个索引联合,然后补充父母
    class Meta:
        unique_together = ('name', 'video_type', 'from_to', 'nationality')
        
    def __str__(self):
        return self.name

db_index 对模型中的某个字段建立数据库索引。

定义一个演员附表:

# 定义一个演员附表
class VideoStar(models.Model):
    video = models.ForeignKey(Video, 
                              related_name='video_star', 
                              on_delete=models.SET_NULL, 
                              blank=True,
                              null=True
                              )
    name = models.CharField(max_length=100, null=False)
    identity = models.CharField(max_length=50, default='')  # 身份,导演、主演。。
    
    # 唯一性
    class Meta:
        unique_together = ('video', 'name', 'identity')
        
    def __str__(self):
        return self.name

外键中的related_name,可以使主表的对象,通过这个related_name反向查找,找出和主表该对象关联的附表中的对象。使用时就是:表1.related_name.get() 。这里的related_name就替换成related_name里的值就可以了。就可以找到该movie对象对应的star对象了。

视频相关的附属表:

# 视频的附属表:如视频地址、播放集数
class VideoSub(models.Model):
    video = models.ForeignKey(Video,
                              related_name='video_sub',
                              on_delete=models.SET_NULL,
                              blank=True,
                              null=True
                              )  # 外键和上面一样
    url = models.CharField(max_length=500, null=False)
    number = models.IntegerField(default=1)  # 集数
    
    class Meta:
        unique_together = ('video', 'number')
    
    def __str__(self):
        return 'video:{}  number:{} '.format(self.video.name, self.number)

注意:还有一点就是在建立外键时,on_delete=models.SET_NULL,所以后面一定要加上:null=True
我最开始没加所以报了个错误:
Django项目练习(五)——用户表开发&视频表结构开发

三、同步数据库

python manage.py makemigrations

提示说:No changes detected。
因为真正要读取的是app目录下的models.py文件中的
所以要把我们刚刚写的表引入到models中:

# coding:utf-8

from .model.auth import ClientUser
from .model.video import Video, VideoStar, VideoSub

然后在更新数据库,创建出来了
Django项目练习(五)——用户表开发&视频表结构开发
然后再migrate。

上一篇:Django ORM中常用字段和参数


下一篇:【Django】创建用户,继承AbstractUser自定义用户模型类