django学习之- Models笔记
Posted 十年如一..bj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django学习之- Models笔记相关的知识,希望对你有一定的参考价值。
1:创建数据库表
#单表
# app01_user 生成的表明为 tb1
class User(models.Model):
name = models.CharField(max_length=32,db_index=True) # 单列创建索引
email = models.CharField(max_length=32)
class Meta: # 生成的表名:tb1
#数据库中生成的表名称,默认app名称+下划线+类名
db_table=\'tb1\' (重要)
index_together={ (\'name\',\'email\')} # 这就是联合索引,如用户名+密码验证(重要)
# 联合索引根据最左前缀的模式,name最左
# select * from where name = \'xx\' 命中索引速度快
# select * from where name = \'xx\' and email=\'xx\' 命中索引速度快
# select * from where email=\'xx\' 无法命中索引速度慢
unique_together=((\'name\',\'email),) # 联合唯一索引,组合唯一(重要)
verbose_name = \'上课记录\'
verbose_name_plural = \'上课记录\' # admin里生成的表名
# 一对多/一对一/多对多,其中一对一和多对多都是基于一对多衍生出来的。
一对多,重要参数:on_delete,related_name,
class UserType(models.Model):
name = models.CharField(max_length=32)
class User(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
ForiegnKey(to=\'UserTyep\',to_field=\'id\',on_delete=models.CASCADE) #on_delete有多个选项,这里这个选项表示删除一个类型,将会删除此类型对应的所有用户
多表关系以及参数
ForeignKey(ForeignObject) # ForeignObject(RelatedField) to, # 要进行关联的表名 to_field=None, # 要关联的表中的字段名称 on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为 - models.CASCADE,删除关联数据,与之关联也删除 - models.DO_NOTHING,删除关联数据,引发错误IntegrityError,是数据库操作后库级别抛出的 - models.PROTECT,删除关联数据,引发错误ProtectedError,是受保护的,由django级别抛出的 - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空) - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值) - models.SET,删除关联数据, a. 与之关联的值设置为指定值,设置:models.SET(值) b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象) def func(): return 10 class MyModel(models.Model): user = models.ForeignKey( to="User", to_field="id" on_delete=models.SET(func),) related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values(\'表名__字段名\') limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: # 如: - limit_choices_to={\'nid__gt\': 5} - limit_choices_to=lambda : {\'nid__gt\': 5} from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=\'root\') db_constraint=True # 是否在数据库中创建外键约束 parent_link=False # 在Admin中是否显示关联数据 OneToOneField(ForeignKey) to, # 要进行关联的表名 to_field=None # 要关联的表中的字段名称 on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为 ###### 对于一对一 ###### # 1. 一对一其实就是 一对多 + 唯一索引 # 2.当两个类之间有继承关系时,默认会创建一个一对一字段 # 如下会在A表中额外增加一个c_ptr_id列且唯一: class C(models.Model): nid = models.AutoField(primary_key=True) part = models.CharField(max_length=12) class A(C): id = models.AutoField(primary_key=True) code = models.CharField(max_length=1) ManyToManyField(RelatedField) to, # 要进行关联的表名 related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values(\'表名__字段名\') limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: # 如: - limit_choices_to={\'nid__gt\': 5} - limit_choices_to=lambda : {\'nid__gt\': 5} from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=\'root\') symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段 # 做如下操作时,不同的symmetrical会有不同的可选字段 models.BB.objects.filter(...) # 可选字段有:code, id, m1 class BB(models.Model): code = models.CharField(max_length=12) m1 = models.ManyToManyField(\'self\',symmetrical=True) # 可选字段有: bb, code, id, m1 class BB(models.Model): code = models.CharField(max_length=12) m1 = models.ManyToManyField(\'self\',symmetrical=False) through=None, # 自定义第三张表时,使用字段用于指定关系表 through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表 from django.db import models class Person(models.Model): name = models.CharField(max_length=50) class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField( Person, through=\'Membership\', through_fields=(\'group\', \'person\'), ) class Membership(models.Model): group = models.ForeignKey(Group, on_delete=models.CASCADE) person = models.ForeignKey(Person, on_delete=models.CASCADE) inviter = models.ForeignKey( Person, on_delete=models.CASCADE, related_name="membership_invites", ) invite_reason = models.CharField(max_length=64) db_constraint=True, # 是否在数据库中创建外键约束 db_table=None, # 默认创建第三张表时,数据库中表的名称
实例:通过外键实现2个表的正反向操作
models代码
![](https://image.cha138.com/20210606/df5eab31c22a470894b8c962044f9571.jpg)
class UserType(models.Model): name = models.CharField(max_length=32) class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) ut = models.ForiegnKey(to=\'UserTyep\', to_field=\'id\')
views代码
![](https://image.cha138.com/20210606/df5eab31c22a470894b8c962044f9571.jpg)
def index(request): # 正向操作 v = models.User.objects.all() for item in v: print(v.user) print(v.pwd) print(v.ut.name) # 这个实现跨表操作 # 跨表提取指定的字段: ut__name为UserType的name字段 h = models.User.objects.all().values(\'user\',\'ut__name\') # 反向操作 v = models.UserType.objects.all() for item in v: print(item.name) print(item.user_set.all()) # 提取当前类型对应的所有用户 # 跨表提取指定的字段: ut__name为UserType的name字段 h = models.UserType.objects.all().values(\'name\',\'user__pwd\') return HttpResponse(\'index\')
另:
# 使用参数:related_name=\'b\' ,反向查询写法:item.b.all()
# 使用参数:related_query_name=\'a\' 反向查询写法:item.a_set.all()
# 一对一,继承外键,并且加入了唯一约束
OneToOneField(ForeignKey)
to, # 要进行关联的表名
to_field=None # 要关联的表中的字段名称
on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
# 多对多,关注参数:through,through_fields=None(当使用第3种方法时使用)
1:django创建第三张表,增删改查方法如下:
m2m.add/remove/set/clear/filter
2:自己创建第三章表(没有m2m字段),要自己实现第三章表的链表查询
实例:
class Blog(models.Model):
site = models.CharField(max_length=32)
class Tag(models.Model):
name = models.CharField(max_length=32)
class B2T(models.Model):
b = models.ForeignKey(\'Blog\')
t = models.ForeignKey(\'Tag\')
3:自定义第三张表,(有m2m字段)
# 通过m2m字段查操作
# 通过m2m字段 clear
实例:通过through指定第三张表,通过through_field指定第三张表的关联字段,会创建3张表,第三张表的操作需要自己手工对B2T表操作
class Blog(models.Model):
site = models.CharField(max_length=32)
m = models.ManyToManyField(\'Tag\',through=\'B2T\',through_field=[\'b\',\'t1\'] # 只能实现查询对Tag表
class Tag(models.Model):
name = models.CharField(max_length=32)
class B2T(models.Model):
b = models.ForeignKey(\'Blog\')
t1 = models.ForeignKey(\'Tag\')
t2 = models.ForeignKey(\'Tag\')
常用操作记录
![](https://image.cha138.com/20210606/df5eab31c22a470894b8c962044f9571.jpg)
1 # 获取个数 2 # 3 # models.Tb1.objects.filter(name=\'seven\').count() 4 5 # 大于,小于 6 # 7 # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 8 # models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值 9 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 10 # models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值 11 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 12 13 # in 14 # 15 # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 16 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 17 18 # isnull 19 # Entry.objects.filter(pub_date__isnull=True) 20 21 # contains 22 # 23 # models.Tb1.objects.filter(name__contains="ven") 24 # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 25 # models.Tb1.objects.exclude(name__icontains="ven") 26 27 # range 28 # 29 # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and 30 31 # 其他类似 32 # 33 # startswith,istartswith, endswith, iendswith, 34 35 # order by 36 # 37 # models.Tb1.objects.filter(name=\'seven\').order_by(\'id\') # asc 38 # models.Tb1.objects.filter(name=\'seven\').order_by(\'-id\') # desc 39 40 # group by 41 # 42 # from django.db.models import Count, Min, Max, Sum 43 # models.Tb1.objects.filter(c1=1).values(\'id\').annotate(c=Count(\'num\')) 44 # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" 45 46 # limit 、offset 47 # 48 # models.Tb1.objects.all()[10:20] 49 50 # regex正则匹配,iregex 不区分大小写 51 # 52 # Entry.objects.get(title__regex=r\'^(An?|The) +\') 53 # Entry.objects.get(title__iregex=r\'^(an?|the) +\') 54 55 # date 56 # 57 # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) 58 # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) 59 60 # year 61 # 62 # Entry.objects.filter(pub_date__year=2005) 63 # Entry.objects.filter(pub_date__year__gte=2005) 64 65 # month 66 # 67 # Entry.objects.filter(pub_date__month=12) 68 # Entry.objects.filter(pub_date__month__gte=6) 69 70 # day 71 # 72 # Entry.objects.filter(pub_date__day=3) 73 # Entry.objects.filter(pub_date__day__gte=3) 74 75 # week_day 76 # 77 # Entry.objects.filter(pub_date__week_day=2) 78 # Entry.objects.filter(pub_date__week_day__gte=2) 79 80 # hour 81 # 82 # Event.objects.filter(timestamp__hour=23) 83 # Event.objects.filter(time__hour=5) 84 # Event.objects.filter(timestamp__hour__gte=12) 85 86 # minute 87 # 88 # Event.objects.filter(timestamp__minute=29) 89 # Event.objects.filter(time__minute=46) 90 # Event.objects.filter(timestamp__minute__gte=29) 91 92 # second 93 # 94 # Event.objects.filter(timestamp__second=31) 95 # Event.objects.filter(time__second=2) 96 # Event.objects.filter(timestamp__second__gte=31)
querySet包含的功能
![](https://image.cha138.com/20210606/df5eab31c22a470894b8c962044f9571.jpg)
################################################################## # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET # ################################################################## def all(self) # 获取所有的数据对象 def filter(self, *args, **kwargs) # 条件查询 # 条件可以是:参数,字典,Q def exclude(self, *args, **kwargs) # 条件查询 # 条件可以是:参数,字典,Q def select_related(self, *fields) 性能相关:表之间进行join连表操作,一次性获取关联的数据。 model.tb.objects.all().select_related() model.tb.objects.all().select_related(\'外键字段\') model.tb.objects.all().select_related(\'外键字段__外键字段\') def prefetch_related(self, *lookups) 性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。 # 获取所有用户表 # 获取用户类型表where id in (用户表中的查到的所有用户ID) models.UserInfo.objects.prefetch_related(\'外键字段\') from django.db.models import Count, Case, When, IntegerField Article.objects.annotate( numviews=Count(Case( When(readership__what_time__lt=treshold, then=1), output_field=CharField(), )) ) students = Student.objects.all().annotate(num_excused_absences=models.Sum( models.Case( models.When(absence__type=\'Excused\', then=1), default=0, output_field=models.IntegerField() ))) def annotate(self, *args, **kwargs) # 用于实现聚合group by查询 from django.db.models import Count, Avg, Max, Min, Sum v = models.UserInfo.objects.values(\'u_id\').annotate(uid=Count(\'u_id\')) # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id v = models.UserInfo.objects.values(\'u_id\').annotate(uid=Count(\'u_id\')).filter(uid__gt=1) #这里的filter相当于having # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 v = models.UserInfo.objects.values(\'u_id\').annotate(uid=Count(\'u_id\',distinct=True)).filter(uid__gt=1) # distinct去重 # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 def distinct(self, *field_names) # 用于distinct去重 models.UserInfo.objects.values(\'nid\').distinct() # select distinct nid from userinfo 注:只有在PostgreSQL中才能使用distinct进行去重 def order_by(self, *field_names) # 用于排序 models.UserInfo.objects.all().order_by(\'-id\',\'age\') def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # 构造额外的查询条件或者映射,如:子查询 Entry.objects.extra(select={\'new_id\': "select col from sometable where othercol > %s"}, select_params=(1,)) Entry.objects.extra(where=[\'headline=%s\'], params=[\'Lennon\']) Entry.objects.extra(where=["foo=\'a\' OR bar = \'a\'", "baz = \'a\'"]) Entry.objects.extra(select={\'new_id\': "select id from tb where id > %s"}, select_params=(1,), order_by=[\'-nid\']) def reverse(self): # 倒序 models.UserInfo.objects.all().order_by(\'-nid\').reverse() # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序 def defer(self, *fields): models.UserInfo.objects.defer(\'username\',\'id\') 或 models.UserInfo.objects.filter(...).defer(\'username\',\'id\') #映射中排除某列数据 def only(self, *fields): #仅取某个表中的数据 models.UserInfo.objects.only(\'username\',\'id\') 或 models.UserInfo.objects.filter(...).only(\'username\',\'id\') def using(self, alias): 指定使用的数据库,参数为别名(setting中的设置) ################################################## # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS # ################################################## def raw(self, raw_query, params=None, translations=None, using=None): # 执行原生SQL models.UserInfo.objects.raw(\'select * from userinfo\') # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名 models.UserInfo.objects.raw(\'select id as nid from 其他表\') # 为原生SQL设置参数 models.UserInfo.objects.raw(\'select id as nid from userinfo where nid>%s\', params=[12,]) # 将获取的到列名转换为指定列名 name_map = {\'first\': \'first_name\', \'last\': \'last_name\', \'bd\': \'birth_date\', \'pk\': \'id\'} Person.objects.raw(\'SELECT * FROM some_other_table\', translations=name_map) # 指定数据库 models.UserInfo.objects.raw(\'select * from userinfo\', using="default") ################### 原生SQL ################### from django.db import connection, connections cursor = connection.cursor() # cursor = connections[\'default\'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() # fetchall()/fetchmany(..) def values(self, *fields): # 获取每行数据为字典格式 def values_list(self, *fields, **kwargs): # 获取每行数据为元祖 def dates(self, field_name, kind, order=\'ASC\'): # 根据时间进行某一部分进行去重查找并截取指定内容 # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日) # order只能是:"ASC" "DESC" # 并获取转换后的时间 - year : 年-01-01 - month: 年-月-01 - day : 年-月-日 models.DatePlus.objects.dates(\'ctime\',\'day\',\'DESC\') def datetimes(self, field_name, kind, order=\'ASC\', tzinfo=None): # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间 # kind只能是 "year", "month", "day", "hour", "minute", "second" # order只能是:"ASC" "DESC" # tzinfo时区对象 models.DDD.objects.datetimes(\'ctime\',\'hour\',tzinfo=pytz.UTC) models.DDD.objects.datetimes(\'ctime\',\'hour\',tzinfo=pytz.timezone(\'Asia/Shanghai\')) """ pip3 install pytz import pytz pytz.all_timezones pytz.timezone(‘Asia/Shanghai’) """ def none(self): # 空QuerySet对象 #################################### # METHODS THAT DO DATABASE QUERIES # #################################### def aggregate(self, *args, **kwargs): # 聚合函数,获取字典类型聚合结果 from django.db.models import Count, Avg, Max, Min, Sum result = models.UserInfo.objects.aggregate(k=Count(\'u_id\', distinct=True), n=Count(\'nid\')) ===> {\'k\': 3, \'n\': 4} def count(self): # 获取个数 def get(self, *args, **kwargs): # 获取单个对象 def create(self, **kwargs): # 创建对象以上是关于django学习之- Models笔记的主要内容,如果未能解决你的问题,请参考以下文章