第一章 django安装与介绍
第二章 django基础使用
第三章 路由层
第四章 虚拟环境、django版本区别、视图层
第五章 模板层
第六章 模型层(上)
1.创建任意py文件
2.py文件中加上固定的测试环境
from django.test import TestCase
import os
if __name__ == "__main__":
# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "项目文件.settings文件")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djtest.settings")
import django
django.setup()
#在此处开始编写测试代码
除了使用测试文件测试之外还可以是使用pycharm提供的测试环境来测试。
点击左下方的python console在其中直接编写测试代码即可
方式1:如果结果集对象是queryset 那么可以直接点query查看
方式2:配置文件固定配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
字段
AutoField
int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
IntegerField
一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,)
CharField
字符类型,必须提供max_length参数, max_length表示字符长度。
DateField
日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。
DateTimeField
日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。
DecimalField
浮点型字段,max_digits数字允许的最大位数,decimal_places小数的最大位数
BigIntergerField
对应mysql的bigintterger类型
BooleanField
存储的值在python对应False和True,但存在数据库中为1或0,使用时会自动将数据库中的0或1转换为布尔值
TextField
存储大段文本
FileField
传文件自动保存到指定位置然后数据库中存储相应的文件路径
EmailField
在mysql中本质还是varchar类型 ,知识在python中会自动检测输入的字符串是否符合邮箱格式
自定义字段
在模型层中每一个字段实际上都是一个python类,自定义字段就是自定义python类来继承django自己的字段类,自定义字段中可以设计新方法,也可以继承Field中的方法然后重写
eg:
class MyCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super().__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection): # 返回该字段在数据库中的类型,除此之外还有别的方法
参数
primary_key
用于设置主键primary_key = True
max_length
用于设置字段长度max_length=20
verbose_name
用于外键字段设置正向查询的名称verbose_name = “fk1”
null
设置字段是否可以为空null = True
default
设置字段默认值default = 5
max_digits
数字允许的最大位数max_digits=5
decimal_places
小数允许的最大位数decimal_places=4
unique
是否设置唯一unique=True
db_index
设置为索引db_index = True
auto_now
每次修改字段所在表,字段值自动更新为修改时间auto_now = True
auto_now_add
第一次添加记录时,字段值变为添加时间auto_now_add = True
choices
用于可以被列举完全的数据
eg:
class User(models.Model):
username = models.CharField(max_length=30)
password = models.CharField(max_length=16)
gender_choice = ( # gender_choice 可以随意取名
(1,'男性'),
(2,'女性'),
(3,'无')
)
gender = models.IntegerField(choices=gender_choice) #在需要使用的位置choice参数绑定之前创建的choice
User.gender # 获取user表的所有gender数据库中的值 也就是1,2,3
User.get_gender_display() # 获取user表的所有gender我们自己设定的代表值 也就是男性,女性,无
查询所有结果,返回的结果是QuerySet对象
res = models.User.objects.all()
它包含了与所给筛选条件相匹配的对象,返回的结果是QuerySet对象
res = models.User.objects.filter()
返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误,返回的结果为具体的对象
res = models.User.objects.get(uid=2)
它包含了与所给筛选条件不匹配的对象,返回的结果是QuerySet对象
res = models.User.objects.exclude(uid=2)
返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
res = models.User.objects.values("uid", "name", "age")
它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
res = models.User.objects.values_list("name")
对查询结果排序,返回的是QuerySet对象
res = models.User.objects.all().order_by("uid", "name")
对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用,返回的是QuerySet对象
res = models.User.objects.all().reverse("uid")
从返回结果中剔除重复纪录,筛选记录时如果有主键不会生效,返回的是QuerySet对象
res = models.User.objects.values("age").distinct()
返回数据库中匹配查询(QuerySet)的对象数量,返回的是数字
res = models.User.objects.all().count()
返回第一条记录,返回的是具体的对象
res = models.User.objects.all().first()
返回最后一条记录,返回的是具体的对象
res = models.User.objects.all().last()
如果QuerySet包含数据,就返回True,否则返回False
res = models.User.objects.filter("uid=100").exists()
使用方法:
属性+对应的双下查询即可
eg:
models.User.objects.filter(uid_gt=4) 查询用户id大于4的用户
__gt | 大于 |
__lt | 小于 |
__gte | 大于等于 |
__lte | 小于等于 |
__in | 成员运算 如[1,2,3]表示在1或2或3 |
__range | 范围查询 如[1,2]表示在1~2之间包含1、2 |
__contains | 模糊查询区分大小写 |
__icontains | 模糊查询忽略大小写 |
__isnull | 判断是否为空 此处使用示例: 属性__isnull=True/False |
__startswith | 由任意字符串开头的 |
__endswith | 由任意字符串结尾的 |
__regex | 用来书写正则的 |
__year | 按照年份筛选数据 |
__month | 按照月份筛选数据 |
在django1.x版本中外键是自带级联删除的
在2.x以及3.x是需要自行设置的
on_delete
当删除关联表中的数据时,当前表与其关联的行的行为。删除关联数据,与之关联也删除
设置方式 on_delete = models.CASCADE
生成外键是会在对应的表中新增一个字段,该字段一般为外键变量加上_id组成字段名来存储
以下为表的结构
class UserData(models.Model):
createTime = models.DateTimeField(auto_now_add=True)
updateTime = models.DateTimeField(auto_now=True)
class Press(models.Model):
pid = models.AutoField(primary_key=True)
pname = models.CharField(max_length=20)
addres = models.CharField(max_length=20)
class Book(models.Model):
bid = models.AutoField(primary_key=True)
bname = models.CharField(max_length=20)
class User(models.Model):
uid = models.AutoField(primary_key=True)
username = models.CharField(max_length=20)
password = models.CharField(max_length=16)
使用OneToOneField来设定,一对一关系外键可以设置在任意表,但最好设置在经常访问的表
class User(models.Model):
uid = models.AutoField(primary_key=True)
username = models.CharField(max_length=20)
password = models.CharField(max_length=16)
userdata = models.OneToOneField(UserData,# 此参数为连接的表
on_delete=models.CASCADE) # 级联删除
使用ForeignKey来设定,一对多关系外键设置在多的表
uid = models.AutoField(primary_key=True)
username = models.CharField(max_length=20)
password = models.CharField(max_length=16)
press = models.ForeignKey(Press)
使用ManyToManyField来设定,多对多关系外键可以随意设置在任意表,多对多关系django会自动生成一个关系表来储存关系
class User(models.Model):
uid = models.AutoField(primary_key=True)
username = models.CharField(max_length=20)
password = models.CharField(max_length=16)
book = models.ManyToManyField(Book)
向book表增加新书,由于book有外键参照了press表
# 针对于一对一或者一对多时
pobj = models.Press.objects.filter(pid=1).first()
models.User.objects.create(bname="图书3", press_id=1)# 此处向外键传值可以是press_id传对应press表的pid,或者是press=pobj
# 针对多对多时
bobj = models.Book.objects.filter(pid=1).first()
bobj.press.add() # 参数是press对象数据或者对应的主键值,可以是一个或者多个
修改book的记录
# 针对于一对一或者一对多时
pobj = models.Press.objects.filter(pid=1)
models.Book.objects.update(bname="图书3", press_id=1)# 此处向外键传值可以是press_id传对应press表的pid,或者是press=pobj
# 针对于多对多时
bobj = models.Book.objects.filter(bid=1)
bobj.press.set()# 传一个可迭代对象
# 针对于一对一或者一对多时
pobj = models.Press.objects.filter(pid=1).first()
models.Book.objects.filter(bname="图书3", press_id=1).delete()# 此处filter中外键的部分可以是press主键值或者press数据对象
# 针对多对多时
bobj = models.Press.objects.filter(bid=1)
bobj.press.remove() # 括号内可以放主键值也可以放数据对象 并且都支持多个
bobj.press.clear() #括号内无需传值 直接清空当前表在第三张关系表中的绑定记录
核心在于当前数据对象是否含有外键字段 有则是正向 没有则是反向
eg:
class Press(models.Model):
pid = models.AutoField(primary_key=True)
pname = models.CharField(max_length=20)
addres = models.CharField(max_length=20)
class Book(models.Model):
bid = models.AutoField(primary_key=True)
bname = models.CharField(max_length=20)
press = models.ForeignKey(Press)
# 针对上述俩张表,如果从book查找此时是正向,这个时候查询按外键字段名,如果此press查询,这个时候查询按表名小写
基于对象的跨表查询本质就是子查询即分步操作即可
1.先找到第一个表对象
2.表对象点外键属性
eg:
查询出版社id1所属的图书
pobj = models.Press.objects.filter(pid=1).firest()
# 此时查询的俩张表,外键在book所以是反向查询,如果查询到的结果为none接在表名后加上_set
res = pobj.book_set # 如果此时还是none 说明查询结果不是单个需要使用.all()
res = pobj.book_set.all()
基于双下划线的跨表查询本质就是连表操作
eg:
res = models.Book.objects.filter(pname='北方社区').values('press__pname', 'press__addr') # 使用表__属性名 可以获取外键表的字段