models.AutoField() 自增列=int(11),如果没有的话,默认会生成一个名称为id的列,如果要显示的定义一个自增列,必须把该列设置为主键(primary_key=True)
models.IntegerField() 整形(-2147483648, 2147483647)
models.BigIntegerField() 长整形(-9223372036854775808, 9223372036854775807)
models.PositiveIntegerField() 正Integer (0, 2147483647)
models.PositiveSmallIntegerField()正smallInteger (0, 32767)
models.SmallIntegerField() 短整型 (-32768, 32767)
models.Decimal() 十进制小数类型=decimal 必须指定max_digits(总位数)和decimal_places(小数位)
models.FloatField() 浮点类型=double
models.CharField() 字符串类型字段 必须加max_length参数
models.TextField 字符串=longtext
models.BooleanField() 布尔类型字段=tinyint(1) 不能为空blank=True
models.NullBooleanField() 允许为空的布尔类型
models.DateField() 日期字段类型date 参数auto_now=True表示每次更新都会更新这个时间;参数auto_now_add表示只是第一次创建时添加,之后的更新不再改变
models.DateTimeField() 日期字段类型datetime 同DateField的参数
models.TimeField() 时间 HH:MM[:ss[.uuuuuu]]
null=布尔值: 与数据库相关,字段是否允许为空,默认False
blank=布尔值: 与表单验证相关,表单是否允许为空,默认False
defalut=值或对象: 字段默认值,
primary_key=布尔值: 是否主键,默认False
unique=布尔值: 是否唯一,默认False
verbose_name=文本: 字段描述/form中的label值,也可以放到第一个参数models.CharField(“person’s first name”, max_length=30)
db_column 数据库中字段的列名(db_column=“test”)
db_index 设置索引,默认False
editable 是否可编辑,默认为True
help_text 表单帮助信息
choices form中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作, 可通过get_字段_display() 访问字段的显示值
gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
error_messages 自定义错误信息(字典类型),字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能为空.", 'invalid': '格式错误'}
validators 自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
)
max_length: [字符串型] 必须指定数值的参数,utf8编码的最大长度
unique_for_date: [时间日期类型] 日期必须唯一
unique_for_month: [时间日期类型] 月必须唯一
unique_for_year: [时间日期类型] 年必须唯一
auto_now: [时间日期类型] 更新当前时间
auto_now_add: [时间日期类型] 创建时更新当前时间
max_digits: [浮点型] DecimalField字段必须指定,一共多少位
decimal_places: [浮点型] DecimalField字段必须指定,小数点位数
blank主要用在CharField, TextField 这两个字符型字段可用字符串来存储空值
null主要用在IntegerField,DateField,DateTimeField 这几个字段不接受空字符串,所以在使用时,必须将blank和null同时赋值True
class Meta:
db_table = "addressinfo" # 表的名称
ordering = 'pid' # 排序字段
verbose_name = "省市县地址信息"
verbose_name_plural = verbose_name # 复数
unique_together = ("address", "note") # 联合唯一健,还可以用二维元组 ((), ())
app_label = 'app_name' # 模型类属于哪一个应用
# db_tablespace # 定义数据库表空间的名称
# abstract = True # 基类用于继承,默认为False
示例:
from django.db import models
class School(models.Model):
''' 学院 '''
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
def __str__(self):
return "School" .format(self.id, self.name)
class Student(models.Model):
''' 学生 '''
GENDER_CHOICES = (('male', "男"), ('female', "女"), ('secret', "保密"))
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
school = models.ForeignKey('School',
null=True, # 可以为空值
related_name='student', # 反向查询用(就不_set了:d1.student_set.all() -》d1.student )
on_delete=models.CASCADE) # 外键,自动关联表的主键 级联删除
gender = models.CharField(max_length=6, choices=GENDER_CHOICES, default="secret", verbose_name="性别")
introduce = models.TextField(blank=True, verbose_name="介绍")
age = models.IntegerField(default=0, verbose_name="年龄")
rank = models.PositiveIntegerField(default=1, verbose_name="排名", unique=True)
discount = models.DecimalField(max_digits=3, decimal_places=2, verbose_name="折扣", default=1.0)
grade = models.FloatField(default=0.0, verbose_name="成绩")
url = models.URLField(verbose_name="个人主页", max_length=100)
email = models.EmailField(verbose_name="邮箱")
image = models.ImageField(upload_to='img/%Y/%m/%d/', verbose_name='上传图片', null=True)
file = models.FileField(upload_to="file/%Y/%m/%d/", verbose_name="上传文件", blank=True)
is_deleted = models.BooleanField(verbose_name="已删除", default=False, blank=True)
time_added = models.DateTimeField(verbose_name="添加时间", auto_now_add=True, blank=True)
def __str__(self):
return "Student" .format(self.id, self.name, self.school_id)
class Course(models.Model):
''' 课程 '''
id = models.AutoField(primary_key=True)
name= models.CharField(max_length=30)
student = models.ManyToManyField('Student', related_name='course') # 多对多 生成第三张关系表
def delete(self, using=None, keep_parents=False):
self.is_deleted = True
# some actions
self.save()
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
# some actions
self.name = self.name.capitalize() # 首字母大写
return super().save(force_insert=force_insert, force_update=force_update, using=using,
update_fields=update_fields)
def __repr__(self):
return "UserProfile:{}".format(self.name)
def __str__(self):
return self.name
class Meta:
ordering = ['-time_added']
# 对象的默认排序字段,获取对象列表时使用,升序ordering['time_added'],降序ordering['-time_added']
verbose_name = "用户信息"
verbose_name_plural = verbose_name
db_table = "student_info"
添加
s1 = Student(name='张三', school_id=1)
s1.save()
# 或
s2 = Student(name='李四', school=School.objects.get(pk=1))
s2.save()
关联访问
studentObj.school # 属性取值,获取学生对象studentObj的school对象信息
# 通过管理器反向访问
schoolObj.student_set.all()
#或
schoolObj.student.all() # 需要定义related_name='student' 作为反向查询的别名
d1 = School.objects.get(d_id=1)
s1 = Student.objects.get(s_id=1)
c1 = Course.objects.get(c_id=1)
d1.student.all() # 查询到学院的所有学生, 通过一对多关系,管理器.all()
s1.department # 模型类里面的属性,直接访问
c1.student # 管理器 多对多
c1.student.all() # 报名这个课程的学生
s1.course.all() # 学生报名了哪些课程
一对多,多的那头就有这个管理器,有如下方法
添加一指定的模型对象到关联的对象集中
# 将studentObj学生改成schoolObj学院中
schoolObj.student.add(studentObj)
# 先查询后添加
studentObj_QuerySet = Student.objects.filter(id=1)
schoolObj_QuerySet = School.objects.filter(id=1) filter取到的是QuerySet,类似于集合形式
schoolObj_QuerySet[0].student.add(studentObj_QuerySet[0])
# 先创建后添加
s6 = Student(s_name='张三', school_id=1)
s6.save()
schoolObj.student.add(s6)
创建一个新的对象,将它保存并放在关联的对象集返回新创建的对象
studentObj.course.create(name='php') # 会同时向两个表格添加数据
schoolObj.student.create(name='李四') # 给schoolObj学院添加一个学生(之前不存在数据库中)
删除的是关系表中的数据
studentObj.course.remove(courseObj) # 学生取消某个课程
studentObj.course.clear() # 删除的是中间信息表的信息
get(): get(id=1)存在直接返回实例,否则抛出DoesNotExist异常
create() 创建一个model对象,create(title=’’,content=’’,…)
bulk_create() 批量创建
get_or_create() 条件查找,如果没有找到,就调用create创建
update_or_create() 更新时如果不存在则创建
update() 更新 filter().update()
delete() 删除 filter().delete()
count() select count(*) from table
latest() 返回最新的一条记录,需要在model的Meta中定义,get_latest_by = <排序字段>
earliest() 同latest,返回最早的一条记录
first() 当前QuerySet记录中获取第一条
last() 当前QuerySet记录中获取最后一条
exists() 返回boolen
in_bulk() 批量查询
values() filter().values(‘title’)
values_list() filter().values_list(‘title’)
defer: 把不需要展示的字段延迟加载 如all().defer(‘content’) content需要的时候再查询
posts = Post.objects.all().defer('content')
for post in posts: # 执行数据库查询
print(post.content) #再次查询数据库,获取content 【N+1次查询】
only: 同defer,逻辑相反,只获取xxx字段内容
select_related: 处理一对一 关系的N+1查询问题
posts = Post.objects.all().select_related('category')
for post in posts: # 产生数据库查询,category数据也会一次性查询出来
print(post.category)
prefetch_related: 处理多对多 关系的N+1查询问题
posts = Post.objects.all().prefetch_related('tag')
for post in posts: #产生两条查询语句,分别查询post和tag
print(post.tag.all())
__contains、__iscontains 包含,用来进行相似查询
__exact、__iexact 精准匹配
__startswith、__istartswith 以某个字符串开头, like ‘<关键字>%’
__endswith、__iendswith 以某个字符串开头, like ‘<关键字>%’
__gt、__lt、__gte、__lte 比较,相当于>、<、>=、<=
__in 指定某个集合,如:filter(id_in=[1,2,3])
__range 范围查询,多用于时间范围,filter(crated_time__range=(time1,time2)) 相当于 between time1 and time2
__year、__month、__day 日期字段的年/月/日
__isnull True/False
F(): 用来执行数据库层面的计算,避免出现竞争状态
post = Post.objects.get(id=1)
post.pv = F('pv') + 1 # 相当于pv = pv + 1,如果使用post.pv + 1 在多线程有问题
post.save()
Q(): 解决or查询
from django.db.models import Q
Post.objects.filter(Q(id=1) | Q(id=2))
Post.objects.filter(Q(id=1) & Q(id=2))
Count(): 聚合查询
# 某个分类下的文章:
category = Category.objects.get(id=1)
posts_count = category.post_set.count()
# 通过category.post_count()
from django.db.models import Count
categories = Category.objects.annotate(posts_count=Count('post'))
print(categories[0].posts_count)
聚合、分组:
class Student(models.Model):
'''学生类'''
name = models.CharField(max_length=20)
age = models.IntegerField()
hobbies = models.ManyToManyField(Hobby)
class Hobby(models.Model):
'''兴趣类'''
name = models.CharField(max_length=20)
aggregate()聚合方法详解:
from django.db.models import Avg, Max, Min
# 平均年龄
Student.objects.all().aggregate(Avg('age')) # => { 'age__avg': 12 }
Student.objects.aggregate(Avg('age')) # => { 'age__avg': 12 }
# 学生平均年龄, 设置字典的key
Student.objects.aggregate(average_age = Avg('age')) # => { 'average_age': 12 }
# 年龄累计
Student.objects.aggregate(Sum('age')) # => {'age__sum': 144}
# 年龄最大
Student.objects.aggregate(Max('age')) # => {'age__max': 66}
# 同时获取多个聚合
Student.objects.aggregate(Avg('age'), Max('age'), Min('age')) # => {'age__avg': 66, 'age__max': 66, 'age__min': 66}
# 根据Hobby爱好 反查学生最大年龄。查询字段student和age间有双下划线哦。
Hobby.objects.aggregate(Max('student__age')) # => { 'student__age__max': 12 }
**annotate()分组**方法详解:
```python
# 按学生分组,统计每个学生的爱好数量
Student.objects.annotate(hobby_count_by_student=Count('hobbies'))
#按爱好分组,再统计每组学生数量。
Hobby.objects.annotate(Count('student'))