Model组件在django基础篇就已经提到过了,本章介绍更多高级部分。

一、回顾

1、定义表(类)

##单表
from django.db import modelsclass user(models.Model):  #数据库表名为app_classname,比如现在这个表存在数据库中为cmdb_username=models.CharField(max_length=24)   #字符串,最大长度24age=models.IntegerField()  #整数类型##一对多
from django.db import modelsclass user(models.Model):name=models.CharField(max_length=24)age=models.IntegerField()user_group=models.ForeignKey('usergroup',to_field='gid')#外键约束,to_field表示关联的字段,生成的字段为user_group_id,不写的话默认和表的主键关联class usergroup(models.Model):gid=models.AutoField(primary_key=True)groupname=models.CharField(max_length=20,unique=True)ctime=models.DateField(auto_now_add=True)##一对一
from django.db import modelsclass user(models.Model):name=models.CharField(max_length=24)age=models.IntegerField()user_group=models.ForeignKey('usergroup',to_field='gid',unique=True)#加上unique=True确保是一一对应class usergroup(models.Model):gid=models.AutoField(primary_key=True)groupname=models.CharField(max_length=20,unique=True)ctime=models.DateField(auto_now_add=True)###多对多
##########第一种使用传统外键方式关联(自己定义关系)######
class Host(models.Model):hid=models.AutoField(primary_key=True)hostname=models.CharField(max_length=20)ip=models.GenericIPAddressField()class HostGroup(models.Model):gid=models.AutoField(primary_key=True)groupname=models.CharField(max_length=22)
#自己定义第三张表,可以随意添加字段
class HostToGroup(models.Model):hobj=models.ForeignKey(to='Host',to_field="hid")#生成的数据库表字段为hobj_idgobj=models.ForeignKey(to='HostGroup',to_field="gid")#生成的数据库表字段为gobj_id##########第二种使用django自带的方式创建########
class Host(models.Model):hid=models.AutoField(primary_key=True)hostname=models.CharField(max_length=20)ip=models.GenericIPAddressField()class HostGroup(models.Model):gid=models.AutoField(primary_key=True)groupname=models.CharField(max_length=22)hobj=models.ManyToManyField('Host')#使用django自带字段创建第三张表,自动关联主键,数据库表名为cmdb_hostgroup_hobj,这种方式不能直接操作第三张表,可以间接操作#########第三种自定义第三张表,使用django创建m2m关联字段
class Host(models.Model):hid=models.AutoField(primary_key=True)hostname=models.CharField(max_length=20)ip=models.GenericIPAddressField()              m=models.ManyToManyField('HostGrop',through='HostToGroup',through_fields=['hobj','gobj'])#通过自定义m2m关系只能做查询操作class HostGroup(models.Model):gid=models.AutoField(primary_key=True)groupname=models.CharField(max_length=22)
#自己定义第三张表,可以随意添加字段
class HostToGroup(models.Model):hobj=models.ForeignKey(to='Host',to_field="hid")#生成的数据库表字段为hobj_idgobj=models.ForeignKey(to='HostGroup',to_field="gid")#生成的数据库

2、model字段介绍

AutoField(Field)- int自增列,必须填入参数 primary_key=TrueBigAutoField(AutoField)- bigint自增列,必须填入参数 primary_key=True注:当model中如果没有自增列,则自动会创建一个列名为id的列from django.db import modelsclass UserInfo(models.Model):# 自动创建一个列名为id的且为自增的整数列username = models.CharField(max_length=32)class Group(models.Model):# 自定义自增列nid = models.AutoField(primary_key=True)name = models.CharField(max_length=32)SmallIntegerField(IntegerField):- 小整数 -32768 ~ 32767PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)- 正小整数 0 ~ 32767IntegerField(Field)- 整数列(有符号的) -2147483648 ~ 2147483647PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)- 正整数 0 ~ 2147483647BigIntegerField(IntegerField):- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807BooleanField(Field)- 布尔值类型NullBooleanField(Field):- 可以为空的布尔值CharField(Field)- 字符类型- 必须提供max_length参数, max_length表示字符长度TextField(Field)- 文本类型EmailField(CharField):- 字符串类型,Django Admin以及ModelForm中提供验证机制IPAddressField(Field)- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制GenericIPAddressField(Field)- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6- 参数:protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"URLField(CharField)- 字符串类型,Django Admin以及ModelForm中提供验证 URLSlugField(CharField)- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)CommaSeparatedIntegerField(CharField)- 字符串类型,格式必须为逗号分割的数字UUIDField(Field)- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证FilePathField(Field)- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能- 参数:path,                      文件夹路径match=None,                正则匹配recursive=False,           递归下面的文件夹allow_files=True,          允许文件allow_folders=False,       允许文件夹FileField(Field)- 字符串,路径保存在数据库,文件上传到指定目录- 参数:upload_to = ""      上传文件的保存路径storage = None      存储组件,默认django.core.files.storage.FileSystemStorageImageField(FileField)- 字符串,路径保存在数据库,文件上传到指定目录- 参数:upload_to = ""      上传文件的保存路径storage = None      存储组件,默认django.core.files.storage.FileSystemStoragewidth_field=None,   上传图片的高度保存的数据库字段名(字符串)height_field=None   上传图片的宽度保存的数据库字段名(字符串)DateTimeField(DateField)- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]DateField(DateTimeCheckMixin, Field)- 日期格式      YYYY-MM-DDTimeField(DateTimeCheckMixin, Field)- 时间格式      HH:MM[:ss[.uuuuuu]]DurationField(Field)- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型FloatField(Field)- 浮点型DecimalField(Field)- 10进制小数- 参数:max_digits,小数总长度decimal_places,小数位长度BinaryField(Field)- 二进制类型

字段列表

class UnsignedIntegerField(models.IntegerField):def db_type(self, connection):return 'integer UNSIGNED'PS: 返回值为字段在数据库中的属性,Django字段默认的值为:'AutoField': 'integer AUTO_INCREMENT','BigAutoField': 'bigint AUTO_INCREMENT','BinaryField': 'longblob','BooleanField': 'bool','CharField': 'varchar(%(max_length)s)','CommaSeparatedIntegerField': 'varchar(%(max_length)s)','DateField': 'date','DateTimeField': 'datetime','DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)','DurationField': 'bigint','FileField': 'varchar(%(max_length)s)','FilePathField': 'varchar(%(max_length)s)','FloatField': 'double precision','IntegerField': 'integer','BigIntegerField': 'bigint','IPAddressField': 'char(15)','GenericIPAddressField': 'char(39)','NullBooleanField': 'bool','OneToOneField': 'integer','PositiveIntegerField': 'integer UNSIGNED','PositiveSmallIntegerField': 'smallint UNSIGNED','SlugField': 'varchar(%(max_length)s)','SmallIntegerField': 'smallint','TextField': 'longtext','TimeField': 'time','UUIDField': 'char(32)',#####注意事项####
1.触发Model中的验证和错误提示有两种方式:a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息b. 使用ModelFormc. 调用Model对象的 clean_fields 方法,如:# models.pyclass UserInfo(models.Model):nid = models.AutoField(primary_key=True)username = models.CharField(max_length=32)email = models.EmailField(error_messages={'invalid': '格式错了.'})# views.pydef index(request):obj = models.UserInfo(username='11234', email='uu')try:print(obj.clean_fields())except Exception as e:print(e)return HttpResponse('ok')# Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。2.Admin中修改错误提示# admin.pyfrom django.contrib import adminfrom model_club import modelsfrom django import formsclass UserInfoForm(forms.ModelForm):age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'})class Meta:model = models.UserInfo# fields = ('username',)fields = "__all__"exclude = ['title']labels = { 'name':'Writer', }help_texts = {'name':'some useful help text.',}error_messages={ 'name':{'max_length':"this writer name is too long"} }widgets={'name':Textarea(attrs={'cols':80,'rows':20})}class UserInfoAdmin(admin.ModelAdmin):form = UserInfoFormadmin.site.register(models.UserInfo, UserInfoAdmin)

自定义无符号整数字段

3、字段参数

null                数据库中字段是否可以为空db_column           数据库中字段的列名default             数据库中字段的默认值primary_key         数据库中字段是否为主键db_index            数据库中字段是否可以建立索引unique              数据库中字段是否可以建立唯一索引unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引unique_for_month    数据库中字段【月】部分是否可以建立唯一索引unique_for_year     数据库中字段【年】部分是否可以建立唯一索引   verbose_name        Admin中显示的字段名称blank               Admin中是否允许用户输入为空editable            Admin中是否可以编辑help_text           Admin中该字段的提示信息choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作如: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 RegexValidatorfrom 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'), ])####时间的参数
auto_now          #更新时,自动更新为当前时间,仅仅限于obj.save()方法,才会生效

auto_now_add.  #创建时,自动生成

字段参数介绍

4、元数据自定义

通过自定义元数据可以自定义一些特性

class UserInfo(models.Model):nid = models.AutoField(primary_key=True)username = models.CharField(max_length=32)class Meta:# 数据库中生成的表名称 默认 app名称 + 下划线 + 类名db_table = "table_name"  #自定义表名字# 联合索引,最左前缀模式,当查询字段中的where条件必须从pub_date开头才能匹配到索引index_together = [("pub_date", "deadline"),]# 联合唯一索引unique_together = (("driver", "restaurant"),)# admin中显示的表名称
            verbose_name# verbose_name加sverbose_name_plural

5、多表关系参数

ForeignKey(ForeignObject) # ForeignObject(RelatedField)to,                         # 要进行关联的表名to_field=None,              # 要关联的表中的字段名称on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为- models.CASCADE,删除关联数据,与之关联也删除- models.DO_NOTHING,删除关联数据,引发错误IntegrityError- models.PROTECT,删除关联数据,引发错误ProtectedError- models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)- models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)- models.SET,删除关联数据,a. 与之关联的值设置为指定值,设置:models.SET(值)b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)def func():return 10class 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, m1class BB(models.Model):code = models.CharField(max_length=12)m1 = models.ManyToManyField('self',symmetrical=True)# 可选字段有: bb, code, id, m1class BB(models.Model):code = models.CharField(max_length=12)m1 = models.ManyToManyField('self',symmetrical=False)through=None,               # 自定义第三张表时,使用字段用于指定关系表through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表from django.db import modelsclass 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,              # 默认创建第三张表时,数据库中表的名称

二、操作

1.连表正反向查询(反向通过表__set查询)

#####定义表结构
class Usertype(models.Model):name=models.CharField(max_length=30)class person(models.Model):username=models.CharField(max_length=32)pwd=models.CharField(max_length=32)ut=models.ForeignKey(to='Usertype',to_field='id')###正向查询,通过.的方式
v=models.person.objects.all()
for row in v:print(row.username,row.pwd,row.ut.name)###反向查询,默认通过:类名__set获取,字段通过:表__获取,若设置了关联查询参数(related_name),则改变
v1=models.Usertype.objects.all()
for row1 in v1:print(row1.name,row1.id,row1.person_set.all())models.Usertype.objects.values('name','person__username')

2、增、删、改、查

# 增#
        # models.Tb1.objects.create(c1='xx', c2='oo')  增加一条数据,可以接受字典类型数据 **kwargs# obj = models.Tb1(c1='xx', c2='oo')# obj.save()# 查#
        # models.Tb1.objects.get(id=123)         # 获取单条数据,不存在则报错(不建议)# models.Tb1.objects.all()               # 获取全部# models.Tb1.objects.filter(name='seven') # 获取指定条件的数据# models.Tb1.objects.exclude(name='seven') # 获取指定条件的数据# 删#
        # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据# 改# models.Tb1.objects.filter(name='seven').update(gender='0')  # 将指定条件的数据更新,均支持 **kwargs# obj = models.Tb1.objects.get(id=1)# obj.c1 = '111'# obj.save()                                                 # 修改单条数据

3、排序、聚合

# 获取个数#
        # models.Tb1.objects.filter(name='seven').count()# 大于,小于#
        # models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值# models.Tb1.objects.filter(id__gte=1)              # 获取id大于等于1的值# models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值# models.Tb1.objects.filter(id__lte=10)             # 获取id小于10的值# models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值# in#
        # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据# models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in# isnull# Entry.objects.filter(pub_date__isnull=True)# contains#
        # models.Tb1.objects.filter(name__contains="ven")# models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感# models.Tb1.objects.exclude(name__icontains="ven")# range#
        # models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and# 其他类似#
        # startswith,istartswith, endswith, iendswith,# order by#
        # models.Tb1.objects.filter(name='seven').order_by('id')    # asc# models.Tb1.objects.filter(name='seven').order_by('-id')   # desc# group by #当values后面是annotate时候,此时不在时查询,而是分组#
        # from django.db.models import Count, Min, Max, Sum# models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"# limit 、offset#
        # models.Tb1.objects.all()[10:20]# regex正则匹配,iregex 不区分大小写#
        # Entry.objects.get(title__regex=r'^(An?|The) +')# Entry.objects.get(title__iregex=r'^(an?|the) +')# date#
        # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))# Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))# year#
        # Entry.objects.filter(pub_date__year=2005)# Entry.objects.filter(pub_date__year__gte=2005)# month#
        # Entry.objects.filter(pub_date__month=12)# Entry.objects.filter(pub_date__month__gte=6)# day#
        # Entry.objects.filter(pub_date__day=3)# Entry.objects.filter(pub_date__day__gte=3)# week_day#
        # Entry.objects.filter(pub_date__week_day=2)# Entry.objects.filter(pub_date__week_day__gte=2)# hour#
        # Event.objects.filter(timestamp__hour=23)# Event.objects.filter(time__hour=5)# Event.objects.filter(timestamp__hour__gte=12)# minute#
        # Event.objects.filter(timestamp__minute=29)# Event.objects.filter(time__minute=46)# Event.objects.filter(timestamp__minute__gte=29)# second#
        # Event.objects.filter(timestamp__second=31)# Event.objects.filter(time__second=2)# Event.objects.filter(timestamp__second__gte=31)

4、使用子查询和执行原生SQL

# extra#
        # 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'])        #where后面可使用的条件:and条件['id'=>2,'name'='wd'],or条件['id'>2 or 'name'='wd'],使用函数['fund(ctime)=1','name'='wd']#    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'])#这里还可以使用mysql中的函数#Entry.objects.extra(select={'new_id': "func(id)"}, select_params=(1,), order_by=['-nid']) #select_params用于替换%s# F#
        # from django.db.models import F# models.Tb1.objects.update(num=F('num')+1)# Q#
        # 方式一:# Q(nid__gt=10)# Q(nid=8) | Q(nid__gt=10)# Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')# 方式二:# con = Q()# q1 = Q()# q1.connector = 'OR'# q1.children.append(('id', 1))# q1.children.append(('id', 10))# q1.children.append(('id', 9))# q2 = Q()# q2.connector = 'OR'# q2.children.append(('c1', 1))# q2.children.append(('c1', 10))# q2.children.append(('c1', 9))# con.add(q1, 'AND')# con.add(q2, 'AND')#
        # models.Tb1.objects.filter(con)# 执行原生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()

5、QuerySet对象方法详解

##################################################################
# PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
##################################################################def all(self)# 获取所有的数据对象def filter(self, *args, **kwargs)# 条件查询# 条件可以是:参数,字典,Qdef exclude(self, *args, **kwargs)# 条件查询# 条件可以是:参数,字典,Qdef 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, IntegerFieldArticle.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, Sumv = 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)# 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)# SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1def 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):# 执行原生SQLmodels.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, connectionscursor = 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时区对象,需要安装pytzmodels.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))"""pip3 install pytzimport pytzpytz.all_timezonespytz.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, Sumresult = 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):# 创建对象def bulk_create(self, objs, batch_size=None):# 批量插入# batch_size表示一次插入的个数objs = [models.DDD(name='r11'),models.DDD(name='r22')]models.DDD.objects.bulk_create(objs, 10)def get_or_create(self, defaults=None, **kwargs):# 如果存在,则获取,否则,创建# defaults 指定创建时,其他字段的值obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2})def update_or_create(self, defaults=None, **kwargs):# 如果存在,则更新,否则,创建# defaults 指定创建时或更新时的其他字段obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})def first(self):# 获取第一个def last(self):# 获取最后一个def in_bulk(self, id_list=None):# 根据主键ID进行查找id_list = [11,21,31]models.DDD.objects.in_bulk(id_list)def delete(self):# 删除def update(self, **kwargs):# 更新def exists(self):# 是否有结果

QuerySet方法详解

三、model的验证功能以及内置钩子

我们知道,model可以用来对数据库进行操作,但是Django中model提供了弱小的验证功能。

1、验证功能:

通过创建对象使用save方法进行操作创建,在对象中使用full_clean()进行验证,使用异常捕捉来进行处理

user_obj=models.user.objects.create(name='wd',age=22,user_group_id='1')user_obj.full_clean() #验证字段是否正确,通过model字段的正则表达式验证

2、内置钩子

通过创建对象时,会执行顺序执行full_clean()-->clean_fields()-->clean(),我们可以自定义clean函数进行验证,其中clean_fields方法是字段正则验证

class user(models.Model):name=models.CharField(max_length=24)age=models.IntegerField()user_group=models.ForeignKey('usergroup',to_field='gid',null=True,unique=True)#外键约束,to_field表示关联的字段,生成的字段为user_group_iddef clean(self):   #自定义clean验证from django.core.exceptions import ValidationErrorc=user.objects.filter(name=self.name).count()if c:raise ValidationError(message='用户名已经存在',code='00')  #由于clean方法捕获ValidationError,所以我们需要抛出该异常才能被捕获到

转载于:https://www.cnblogs.com/wdliu/p/7693736.html

Django之Model组件相关推荐

  1. Django框架(二十)—— Django rest_framework-认证组件

    Django rest_framework-认证组件 一.什么是认证 只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查看,没有登录,就不能查看,这时候需要用到认证组件 ...

  2. Django之Model操作

    Django之Model操作 本节内容 字段 字段参数 元信息 多表关系及参数 ORM操作 1. 字段 字段列表 AutoField(Field)- int自增列,必须填入参数 primary_key ...

  3. Django之内置组件

    Django组件介绍       分页器的使用       Form       modelForm       orm       cookie和session       中间件       信号 ...

  4. Python之路【第二十二篇】:Django之Model操作

    Django之Model操作 一.字段 AutoField(Field)- int自增列,必须填入参数 primary_key=TrueBigAutoField(AutoField)- bigint自 ...

  5. Django之Form组件介绍

    --------------------------------------前言------------------------------------ 在进入正题之前,想多说两句; 当我们开始学习一 ...

  6. 小白IT:Django框架—form组件和ModelForm

    文章目录 一.form简介 1.form组件的功能 2.form组件的简单使用 数据库模型准备 form简单使用 在视图函数中写注册函数 模板文件login.html文件 二.Form中常用字段约束与 ...

  7. Django中Model继承的三种方式

    Django中Model继承的三种方式 Django中Model的继承有三种: 1.抽象继承 2.多表继承 3.proxy model(代理model) 1.抽象继承 第一种抽象继承,创建一个通用父类 ...

  8. 转载:Django之Form组件

    Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建Form类 + View C ...

  9. Django的model查询操作 与 查询性能优化

    Django的model查询操作 与 查询性能优化 1 如何 在做ORM查询时 查看SQl的执行情况 (1) 最底层的 django.db.connection 在 django shell 中使用 ...

最新文章

  1. Java数据结构类如何使用_Matlab如何使用Java的数据结构类型
  2. Win32 汇编要点总结
  3. 如何用JavaScript判断dom是否有存在某class的值?
  4. 渗透测试工具Burp Suite详解
  5. TransactionScope只要一个操作失败,它会自动回滚,Complete表示事务完成
  6. 计算机导论中IEE是什么缩写,Proc.IEE是期刊吗?全称是什么
  7. python采用编译型方式执行_Python程序的执行过程 解释型语言和编译型语言
  8. 解决QTreeWidget中item无法整行同时显示相同颜色
  9. CreateThread函数
  10. ParserError: Error tokenizing data. C error: Expected 1 fields in line 122, saw 2
  11. android 开源 高斯模糊_Android实现带毛玻璃效果(高斯模糊)背景的Dialog
  12. 图解设计模式(二)适配器模式
  13. 组态王怎么做超级曲线_组态王显示数据并绘制曲线
  14. 回首来时路——李天岩
  15. Kinect+unity 实现体感格斗闯关小游戏
  16. 「效率工具」HHKB的常用快捷键
  17. 最近微信上很火的小游戏【壹秒】android版——开发分享
  18. NP-Hard?大白话学习P问题、NP问题、NP完全问题和NP难问题
  19. 大白兔奶糖三聚氰胺事件后21日起重新上架
  20. .net中的泛型全面解析

热门文章

  1. python获取每月的最后一天_关于日期:使用Python获取本月的最后一天
  2. stm32usb转串口驱动_新品推荐:乐扩PCI-E转8口RS-232串口卡 支持短铁片
  3. cent os 7 mysql_centos – 百胜:Cent OS 7中没有包mysql-server
  4. linux java 选择题_java面试题:Linux
  5. java接口返回类,Java接口和返回类型 - java
  6. spring boot面试_Spring Boot面试问题
  7. Python字符串isalnum()
  8. python ftp_Python FTP
  9. Android拖放– DragLinearLayout
  10. Android Wear Hello World