用户相关开发,客户端表结构开发
一、用户表开发
在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
我最开始没加所以报了个错误:
三、同步数据库
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
然后在更新数据库,创建出来了
然后再migrate。