真的最后一次探究django(模型层)

模型层

关键字字段及参数:

AutoField:
int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列

IntegerField:

一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存)

CharField:

字符类型,必须提供max_length参数, max_length表示字符长度。(数据库中的varchar类型)。

# 自定义char类型

from django.db import models

# Create your models here.
#Django中没有对应的char类型字段,但是我们可以自己创建
class FixCharField(models.Field):
    '''
    自定义的char类型的字段类
    '''
    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):
        '''
        限定生成的数据库表字段类型char,长度为max_length指定的值
        :param connection:
        :return:
        '''
        return 'char(%s)'%self.max_length
#应用上面自定义的char类型
class Class(models.Model):
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=32)
    class_name=FixCharField(max_length=16)
    gender_choice=((1,'男'),(2,'女'),(3,'保密'))
    gender=models.SmallIntegerField(choices=gender_choice,default=3)

DateField:

日期字段,日期格式  YYYY-MM-DD,相当于Python中的datetime.date()实例。

DateTimeField:

日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。

配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

配置上auto_now=True,每次更新数据记录的时候会更新该字段。

字段集合:

AutoField(Field)
        - int自增列,必须填入参数 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必须填入参数 primary_key=True

        注:当model中如果没有自增列,则自动会创建一个列名为id的列
        from django.db import models

        class 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 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整数 0 ~ 32767
    IntegerField(Field)
        - 整数列(有符号的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整数 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807

    BooleanField(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中提供验证 URL

    SlugField(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.FileSystemStorage

    ImageField(FileField)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
            width_field=None,   上传图片的高度保存的数据库字段名(字符串)
            height_field=None   上传图片的宽度保存的数据库字段名(字符串)

    DateTimeField(DateField)
        - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 时间格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

    FloatField(Field)
        - 浮点型

    DecimalField(Field)
        - 10进制小数
        - 参数:
            max_digits,小数总长度
            decimal_places,小数位长度

    BinaryField(Field)
        - 二进制类型

 字段合集

ORM字段与MySQL字段对应关系

对应关系:
    '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)',

字段参数

null: 用于表示某个字段可以为空。

unique:如果设置为unique=True 则该字段在此表中必须是唯一的 。

db_index:如果db_index=True 则代表着为此字段设置索引。

default:为该字段设置默认值。

单独的py文件测试ORM操作需要配置的参数

主要是queryset对象就可以无限制的点queryset方法。

models.User.objects.filter().filter().filter().count()

import os

if __name__ == "__mian__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day58.settings")
    import django
    django.setup()
    from app01 import models # 这句话必须在下面导入,因为django环境创建才能导入

新增数据

# 基于create创建:
user_obj = models.User.objects.create(name='jason',age=18,register_time='2019-6-12')
print(user_obj.register_time)
# 基于对象的绑定方法创建
user_obj = models.User(name='kiven', age=30, register_time='2019-1-1')
user_obj.save()

修改数据

# 基于对象
user_obj = models.User.objects.filter(name='jason').first()
user_obj = 17
user_obj.save()

# 基于queryset
user_obj = models.User.objects.filter(name='jason').update(age=66)

删除数据

# 基于queryset
models.User.objects.fileter(name='jason').delete()

# 基于对象
user_obj = models.User.objects.filter(name='egon').first()
user_obj.delete()

表单查询

<1> all():                  查询所有结果
<2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象,注意多个条件之间是and关系
<3> get(**kwargs):          返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
<4> exclude(**kwargs):      它包含了与所给筛选条件不匹配的对象
<5> order_by(*field):       对查询结果排序('-id')/('price') 默认升序
<6> reverse():              对查询结果反向排序     >>>前面要先有排序才能反向
<7> count():                返回数据库中匹配查询(QuerySet)的对象数量。
<8> first():                返回第一条记录
<9> last():                 返回最后一条记录
<10> exists():              如果QuerySet包含数据,就返回True,否则返回False
<11> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
<12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
<13> distinct():            从返回结果中剔除重复纪录(完全相同的数据包括id)

表单查询之神奇的双下划线查询

models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
 
models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
 
models.Tb1.objects.filter(name__contains="ven")  # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
 
models.Tb1.objects.filter(id__range=[1, 3])      # id范围是1到3的,等价于SQL的bettwen and
 
类似的还有:startswith,istartswith, endswith, iendswith 

date字段还可以:
models.Class.objects.filter(first_day__year=2017)
date字段可以通过在其后加__year,__month,__day等来获取date的特点部分数据
# 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)
需要注意的是在表示一年的时间的时候,我们通常用52周来表示,因为天数是不确定的,老外就是按周来计算薪资的哦~

多表操作

表和表之间的关系:

  • 一对一((OneToOneField):一对一字段无论建在哪张关系表里面都可以,但是推荐建在查询频率比较高的那张表里面
  • 一对多(ForeignKey):一对多字段建在多的那一方
  • 多对多(ManyToManyField):多对多字段无论建在哪张关系表里面都可以,但是推荐建在查询频率比较高的那张表里面
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)
    publish = models.ForeignKey(to='Publish') # to_filed=关联其他字段名,默认主键名
    authors = models.ManyToManyField(to='Author') # 多对多关系 # 虚拟字段 信号字段

class Author(models.Model):
    name = models.CharField(max_length=16)
    age = models.IntegerField()
    authordatail = models.OneToOneField(to='AuthorDatail') # 一对一关系


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)
    email = models.EmailField()

class AuthorDatail(models.Model):
    phone = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)

新增:

# 直接写id
models.Book.obects.create(title='十万个为什么',price=99.9,publish_id=1)
# 传数据对象
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book(title='十万个为什么',price=99.9,publish=publish_obj)

修改:

# 基于queryset修改
models.Book.objects.filter(pk=1).update(publish_id=3)

publish_obj=models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)

# 基于对象的修改
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.publish_id =3   # 点表中真实存在的字段名
book_obj.save()


book_obj = models.Book.objects.filter(pk=1).first()
publish_obj = models.Publish.objects.filter(pk=2).first()
book_obj.publish = publish_obj # 点orm中字段名,传该字段对应的表的数据对象
book_obj.save()

删除:

# 基于queryset
models.Book.objects.filter(pk=1).delete()
models.Publish.objects.filter(pk=2).delete()

# 基于对象
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.delete()

给书籍绑定与作者之间的关系 add() 多对多

 # 给书籍绑定与作者之间的关系(在多对多关系自动生成的表中)
    # 添加关系 add:  add支持传数字或对象,并且可以传多个
    book_obj = models.Book.objects.filter(pk=6).first()
    # book_obj.authors.add(1)
    # book_obj.authors.add(2, 3)

    author_obj = models.Author.objects.filter(pk=2).first()
    author_obj1 = models.Author.objects.filter(pk=3).first()
    # book_obj.authors.add(author_obj)
    book_obj.authors.add(author_obj, author_obj1) #传入多个值

修改书籍与作者的关系 set()

# 修改书籍与作者的关系 set() set()传的必须是可迭代对象
# book_obj = models.Book.objects.filter(pk=6).first()
# 可以传数字或对象,并且支持多个
# book_obj.authors.set((1,)) #我们以元组的形式传值举例
# book_obj.authors.set((1, 2, 3))

# author_list = models.Author.objects.all()
# book_obj = models.Book.objects.filter(pk=6).first()
# book_obj.authors.set(author_list)

删除书籍与作者的绑定关系 remove()

book_obj = models.Book.objects.filter(pk=9).first()
book_obj.authors.remove(1)
book_obj.authors.remove(2,3)

# author_obj = models.Authors.objects.all().first()
author_list = models.Author.objects.all()
# book_obj.authors.remove(author_obj)
book_obj.authors.remove(*author_list) #需将queryset打散 

清空 clear()     清空你当前这个表记录对应的绑定关系

book_obj = models.Book.ojects.filter(pk=9).first()
book_obj.authors.clear()

基于对象的跨表查询

正向查询和反向查询的概念:正向查询按字段,反向查询按表名小写。

一对一:

  • 正向:author————关联字段在author表里————authordetil    按字段
  • 反向:  authordetil————关联字段在author表里————author     按表名小写

一对多:

  • 正向:book————关联字段在book表里————publish    按字段
  • 反向:pblish————关联字段在book表里————book    按表名小写_set.all()  一个出版社对应多本图书

多对多:

  • 正向:book————关联字段在book表里————author      按字段
  • 反向:author————关联字段在book表里————book     按表名小写_set.all() 一个作者对应多本图书

 

    # 基于对象的跨表查询
    # 正向
    # 查询书籍是三国演义的出版社邮箱
    # book_obj = models.Book.objects.filter(title='三国演义').first()
    # print(book_obj.publish.email)
    # 查询书籍是金瓶梅的作者的姓名
    # book_obj = models.Book.objects.filter(title='金瓶梅').first()
    # print(book_obj.authors)  # app01.Author.None
    # print(book_obj.authors.all())
    # 查询作者为jason电话号码
    # user_obj = models.Author.objects.filter(name='jason').first()
    # print(user_obj.authordetail.phone)

    # 反向
    # 查询出版社是东方出版社出版的书籍                  一对多字段的反向查询
    # publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    # print(publish_obj.book_set)  # app01.Book.None
    # print(publish_obj.book_set.all())

    # 查询作者jason写过的所有的书                      多对多字段的反向查询
    # author_obj = models.Author.objects.filter(name='jason').first()
    # print(author_obj.book_set)  # app01.Book.None
    # print(author_obj.book_set.all())

    # 查询作者电话号码是110的作者姓名                   一对一字段的反向查询
    # authordetail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    # print(authordetail_obj.author.name)

    # 基于双下滑线的查询
    # 正向
    # 查询书籍为三国演义的出版社地址
    # res = models.Book.objects.filter(title='三国演义').values('publish__addr','title')
    # print(res)
    # 查询书籍为金瓶梅的作者的姓名
    # res = models.Book.objects.filter(title='金瓶梅').values("authors__name",'title')
    # print(res)
    # 查询作者为jason的家乡
    # res = models.Author.objects.filter(name='jason').values('authordetail__addr')
    # print(res)

    # 反向
    # 查询南方出版社出版的书名
    # res = models.Publish.objects.filter(name='南方出版社').values('book__title')
    # print(res)
    # 查询电话号码为120的作者姓名
    # res = models.AuthorDetail.objects.filter(phone=120).values('author__name')
    # print(res)
    # 查询作者为jason的写的书的名字
    # res = models.Author.objects.filter(name='jason').values('book__title')
    # print(res)
    # 查询书籍为三国演义的作者的电话号码
    # res = models.Book.objects.filter(title='三国演义').values('authors__authordetail__phone')
    # print(res)

    # 查询jason作者的手机号
    # 正向
    # res = models.Author.objects.filter(name='jason').values('authordetail__phone')
    # print(res)
    # 反向
    # res = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
    # print(res)

    # 查询出版社为东方出版社的所有图书的名字和价格
    # 正向
    # res = models.Publish.objects.filter(name='东方出版社').values('book__title','book__price')
    # print(res)
    # 反向
    # res = models.Book.objects.filter(publish__name='东方出版社').values('title','price')
    # print(res)

    # 查询东方出版社出版的价格大于400的书
    # 正向
    # res = models.Publish.objects.filter(name="东方出版社",book__price__gt=400).values('book__title','book__price')
    # print(res)
    # 反向
    # res = models.Book.objects.filter(price__gt=400,publish__name='东方出版社').values('title','price')
    # print(res)

聚合查询和分组查询

    # 聚合查询 aggregate
    # from django.db.models import Max,Min,Count,Sum,Avg
    # 查询所有书籍的作者个数
    # res = models.Book.objects.filter(pk=3).aggregate(count_num=Count('authors'))
    # print(res)
    # 查询所有出版社出版的书的平均价格
    # res = models.Publish.objects.aggregate(avg_price=Avg('book__price'))
    # print(res)  # 4498.636
    # 统计东方出版社出版的书籍的个数
    # res = models.Publish.objects.filter(name='东方出版社').aggregate(count_num=Count('book__id'))
    # print(res)
    # 分组查询(group_by)   annotate
    # 统计每个出版社出版的书的平均价格
    # res = models.Publish.objects.annotate(avg_price=Avg('book__price')).values('name','avg_price')
    # print(res)
    # 统计每一本书的作者个数
    # res = models.Book.objects.annotate(count_num=Count('authors')).values('title','count_num')
    # print(res)
    # 统计出每个出版社卖的最便宜的书的价格
    # res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
    # print(res)
    # 查询每个作者出的书的总价格
    # res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
    # print(res)

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值