zoukankan      html  css  js  c++  java
  • 创建ORM模型

    1.orm模型一般都是放在app的models.py文件中。每个app都可以拥有自己的模型。并且,如果这个模板想要映射到数据库中,那么这个app必须要放在settings,py 的 INSTALLED_APP中进行安装。

    2.这个模型类继承自django.db.modles.Model.不然不能映射到数据库中。这个模型类以后映射到数据库中,表名是app名字小写_类名的小写。字段名是类中定义的属性名。

    3.属性的数据类型映射到表的每个字段的约束类型。是models下的各种filed的实例对象(AutoFileld,CharFileld,DatetimeField)

    4.执行命令 : python manage.py makemigirations 生成迁移脚本文件。

    5 同样执行命令:  python manage.py migrate 将迁移脚本文件映射到数据库中

    通过操作orm模型类来执行数据库的增删改查操作

    1. model类的属性参数

    比如:models.CharField(null=True,blank=True)
    
    (1)null
     
        如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
     
    (1)blank
     
    如果为True,该字段允许不填。默认为False。
    要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
    如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
     
    (2)default
     
    字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
     
    (3)primary_key
     
    如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
    Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
    否则没必要设置任何一个字段的primary_key=True。
     
    (4)unique
     
    如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
     
    (5)choices
    由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
    (6)db_index
      如果db_index=True 则代表着为此字段设置数据库索引。
    
    
    DatetimeField、DateField、TimeField这三个时间字段,都可以设置如下属性。
    
    (7)auto_now_add
        配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
    
    (8)auto_now
        配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。
        只能在save方式时触发自动更新时间的动作

    ORM数据库增删改查动作

    添加单条数据复制代码

    from django.shortcuts import render,HttpResponse
    from app01 import models
    def add_book(request):
        import datetime
        # 添加数据
        # 方式一
        book_obj = models.Mybook(
            title='看不见的光',
            state=True,
            pub_date='2010-03-04',
            price=45.5,
            publish='人民出版社'
        )
        print(book_obj.title)
        print(book_obj.price)
        book_obj.save() # 这是保存数据
    
        return HttpResponse('已添加')
    
        # 方式二:
        book_obj = models.Mybook.objects.create(
            title='激荡十年',
            state=True,
            # 日期时间类型数据,通过字符串或者日期时间类型数据作为参数数据,都是可以的
            pub_date=datetime.datetime.now(),
            price=39.9,
            publish='北京出版社'
        )
        print(book_obj)
        print(book_obj.title)
        print(book_obj.price)
        # 重点记录:create方法会返回新添加的这条记录的类对象,通过这个对象.属性的方式能够获取到对应字段的数据
        return HttpResponse('操作成功')
    复制代码

    批量添加数据: 使用bulk_create

    复制代码
    from django.shortcuts import render,HttpResponse
    from app01 import models
    def add_book(request):
        obj_list = []
        for i in range(1,10):
            obj = models.Mybook(
                title=f'大国的博弈{i}',
                state=True,
                pub_date=f'2018-07-{i}',
                price=35+i,
                publish='云出版社'
            )
            obj_list.append(obj)
        models.Mybook.objects.bulk_create((obj_list))
        return HttpResponse('已批量添加')
     

    更新或添加: Update_or_create()

     
      # 有就更新的操作
        models.Mybook.objects.update_or_create(
            id=5,
            defaults={
                'title':'边城',
                'state':True,
                'pub_date':'2018-07-05',
                'price':29.9,
                'publish':'人民出版社'
            }
        )
    
        # 没有就创建的案例
        models.Mybook.objects.update_or_create(
            id=20,
            defaults={
                'title': '边城',
                'state': True,
                'pub_date': '2018-07-05',
                'price': 29.9,
                'publish': '人民出版社'
            }
        )
    
        # 查询为多条记录: 报错,因为update_or_create内部进行查询时用的get方法
        # get() returned more than one Mybook -- it returned 8!
        models.Mybook.objects.update_or_create(
            publish='人民出版社',
            defaults={
                'title': '三三',
                'state': True,
                'pub_date': '2018-07-05',
                'price': 29.9,
                'publish': '人民出版社'
            }
        )
    
        return HttpResponse('ok')
     

    查询或添加: get_or_create()

     
    ret = models.Mybook.objects.get_or_create(
            id=15,
            defaults={
                'title': '三三',
                'state': True,
                'pub_date': '2018-07-05',
                'price': 29.9,
                'publish': '人民出版社'
            }
        )
        print(ret) # (<Mybook: 大国的博弈7>, False)  id为15是有数据的, 所以直接返回数据了, 没有创建, 返回结果元祖中第二个值为False
        # 没数据创建数据
        ret = models.Mybook.objects.get_or_create(
            id=50,
            defaults={
                'title': '三三',
                'state': True,
                'pub_date': '2018-07-05',
                'price': 29.9,
                'publish': '人民出版社'
            }
        )
        print(ret) # (<Mybook: 三三>, True)  id为50是没有数据的, 所以创建数据了,  返回结果元祖中第二个值为True
    
        return HttpResponse('ok')
     

    (2) 几种查询方法

    all()查询所有的数据,返回结果为QuerySet类型数据,QuerySet类似于列表,里面存放的是model类的实例化对象,每个对象表示一条记录,对象中的对应数据有着该行记录的字段数据

     
    def get_book(request):
        obj_list = models.Mybook.objects.all()
        print(obj_list[0]) # 索引取值
        print(obj_list[1:4]) # 切片取值
    
        return HttpResponse('OK')
    # QuerySet类似于列表,但是比列表还多一些其他的功能,这是orm封装出来的新的数据类型
    # <QuerySet [<Mybook: 看不见的光>, <Mybook: 看不见的光>, <Mybook: 看不见的光>]>
     

    filter() 过滤查询 ,结果也是queryset类型数据,里面的每一项也是模型类对象, 查找不到内容时, 返回空的查询结果集

    obj_list = models.Mybook.objects.filter(id=9)
        print(obj_list) # <QuerySet [<Mybook: 大国的博弈1>]>
    obj_list = models.Mybook.objects.filter(publish='北京出版社')
        print(obj_list) # <QuerySet [<Mybook: 看不见的光>, <Mybook: 激荡十年>]> 查找内容可以是多项

    get() 过滤查询,但是结果有且只能有一条,结果不是queryset类型数据,而是一个模型类对象

     
    obj = models.Mybook.objects.get(id=5)
        print(obj) # Mybook object
        print(obj.price) # 29.90000
    
        # 当查询结果有多项时, 报错
        obj = models.Mybook.objects.get(publish='北京出版社')
        print(obj)
        # get() returned more than one Mybook -- it returned 2!
    
        # 当查询不到数据时 也会报错
        obj = models.Mybook.objects.get(id=80)
        print(obj)
        # Mybook matching query does not exist.
     

    修改

     
    def update_book(request):
        # 方式一: 模型类对象修改数据
        obj = models.Mybook.objects.get(id=5)
        obj.title = '我的前半生'
        obj.price = 49
        obj.save()
    
        # 方式二: update方法, 调用者可以是objects控制器, 也可以是queryset类型数据, 但是不能是模型类对象
        # (1) objects调用, 整列更新
        models.Mybook.objects.update(
            state = False
        )
        # (2) queryset调用, 整列更新
        models.Mybook.objects.all().update(
            state = True
        )
    
        # (3) queryset类型数据调用, 更新部分数据
        obj = models.Mybook.objects.filter(publish='云出版社').update(
            price = 19.9
        )
        print(obj) # 9 返回受影响的行数
    
    
        # 模型类数据调用update方法的错误演示如下
        models.Mybook.objects.get(id=7).update(
            price = 66
        )
        # 'Mybook' object has no attribute 'update'
     

    删除: delete

     
    def del_book(request):
        # 调用者可以是model对象, 也可以是queryset对象
        obj = models.Mybook.objects.get(id=5).delete()
        print(obj) # (1, {'app01.Mybook': 1}) 返回结果是受影响的行数
    
        obj = models.Mybook.objects.filter(publish='人民出版社').delete()
        print(obj) # (7, {'app01.Mybook': 7})
    
        # 错误演示:
        obj = models.Mybook.objects.delete()
        # 'Manager' object has no attribute 'delete'
        # 控制器没有delete方法,原因就是怕一下子删除了所有数据
    
        # obj = models.Mybook.objects.all().delete()
        # 这个是删除所有数据
    
        return HttpResponse('OK')
     

    查询的13个API接口

    (1)  all():       查询所有结果,结果是queryset类型

    (2)  filter(**kwargs):       它包含了与所给筛选条件相匹配的对象,结果也是queryset类型,可以被queryset类型数据调用,也可以直接通过objects控制器进行调用:

    models.Book.objects.filter(id=5) #filter(id!=5)  不能直接写不等于,想做不等于排除查询使用下面的exclude方法
    models.Book.objects.all().filter(id=5)
    models.Book.objects.filter(title='linux',price=100) 

    #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系的在这里写是搞不定的

    (3)  get(**kwargs):          返回与所给筛选条件相匹配的对象,结果不是queryset类型,是行记录(模型类对象)对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。用的时候最好带上捕获异常try, get方法调用者可以是queryset类型数据,也可以是objects控制器。 

    models.Book.objects.get(id=1)
    models.Book.objects.all().get(id=8)

    (4)  exclude(**kwargs):      排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 ,调用者可以是queryset类型数据,也可以是objects控制器。 

    obj = models.Mybook.objects.exclude(id=4)
        print(obj)

    (5) order_by(*field):   对查询结果排序, 返回值还是queryset类型,调用者可以是queryset类型数据,也可以是objects控制器。

     
    models.Book.objects.order_by('price') #获取所有数据,并且按照price字段升序排列
    models.Book.objects.order_by('-price') #获取所有数据,并且按照price字段降序排列
    models.Book.objects.all().order_by('-price') #queryset类型数据调用
        
    多条排序示例:
    models.Book.objects.all().order_by('price','id') 

    #直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-price'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
     

    (6) reverse(): 可以是queryset类型的数据来调用,也可以是objects控制器调用,对查询结果反向排序,返回值还是queryset类型

     
    方式1:
    order_by(*field)方法进行排序
    obj_list = models.Book.objects.all().order_by('id').reverse() 方式2: 在模型类中通过Meta类来执行排序规则 class Book(models.Model): id = models.AutoField(primary_key=True) #自增、主键 title = models.CharField(max_length=64,null=True) # state = models.BooleanField(default=True) pub_date = models.DateField(null=True) # price = models.DecimalField(max_digits=20,decimal_places=5,null=True) price = models.DecimalField(max_digits=8,decimal_places=2,null=True) publish = models.CharField(max_length=32) def __str__(self): return self.title + '价格' + str(self.price) class Meta: ordering = ['id',] #制定了它之后,所有的本表的查询结果,都按照id进行升序排列,还可进行多条件排序规则的指定
    obj_list = models.Book.objects.reverse()
    reverse()翻转,必须在上面两者的基础上,才能进行结果顺序翻转
     

     (7) count():   queryset类型的数据来调用,也可以是objects控制器调用,返回数据库中匹配查询(QuerySet)的对象数量。返回结果是个数字。

    obj_list = models.Book.objects.count() #默认统计的整表的所有数据量
    obj_list = models.Book.objects.all().count()

    (8)  first():  queryset类型的数据来调用,也可以是objects控制器调用,返回第一条记录对象,结果得到的都是model对象,不是queryset

    Book.objects.all().first()  #同:Book.objects.all()[0] 
    Book.objects.first()

    (9)  last():    queryset类型的数据来调用,也可以是objects控制器调用,返回最后一条记录对象,结果得到的都是model对象,不是queryset

    Book.objects.all().last()  
    #同:Book.objects.all()[-1] ,但是负数索引取值会报错,错误信息为: Negative indexing is not supported. queryset类型数据,不支持负数索引取值的形式 Book.objects.last()

    (10)  exists():   queryset类型的数据来调用,也可以是objects控制器调用,如果QuerySet包含数据,就返回True,否则返回False

     
    obj_list = models.Book.objects.exists() #判断表中是否有数据
    obj_list = models.Book.objects.filter(id=100).exists()  #判断查询结果集中是否有数据,有得到True,没有得到False
        
    注意:
    空的queryset类型数据布尔值为False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,那么就需要查询出所有的数据,效率太差了,用count或者exists
    
    #'select * from book where name="xx";'
    # if obj_list:  会将满足条件的所有数据进行一次查询,效率低
    
    #select count(id) from book where name='xx';
    # if obj_list.count(): 效率较高,按照查询结果对象的id值进行个数统计,
    
    #select id from book where name='xx' limit 1; 查询一条数据,不用扫描所有数据
    # if obj_list.exists(): #效率高
        
    例:all_books = models.Book.objects.all().exists() 
    #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
     

    (11)  values(*field):        用的比较多,queryset类型的数据来调用,也可以是objects调用,返回一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,返回的queryset类型,里面的元素是字典数据,既然是queryset类型数据,那么就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。

    # obj_list = models.Book.objects.values() #默认获取的表中所有记录的字典数据,字典中的键是字段名称(模型类属性名称),值是每个字段的对应数据
    # obj_list = models.Book.objects.all().values()
    # 取指定字段数据
    obj_list = models.Mybook.objects.all().values('id','title')
        print(obj_list)
    # <QuerySet [{'id': 7, 'title': '看不见的光'}, {'id': 8, 'title': '激荡十年'},{...}

    (12)  values_list(*field):   它与values()非常相似,它返回的是一个包含元组queryset序列,values返回的是一个包含字典queryset序列

    obj_list = models.Mybook.objects.all().values_list('id','title')
        print(obj_list)
        # <QuerySet [(7, '看不见的光'), (8, '激荡十年'),(...)]

    (13)  distinct():       去重, values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录

     
    class Book(models.Model):
    
        id = models.AutoField(primary_key=True) #自增、主键
            ...
        publish = models.CharField(max_length=32)
    
        def __str__(self):
            return self.title + '价格' + str(self.price)
            
        
        class Meta:
            ordering = ['id','publish',]
    
    
    obj_list = models.Book.objects.all().order_by('publish').values('publish').distinct()

    #当模型类中指定了默认排序字段,那么当我们使用distinct方法进行去重时,默认会按照我们指定的排序字典进行去重,会导致去重结果不是我们想要的,
    所以要么我们在模型类中不指定排序字段,如果指定了排序字段,我们在使用distinct方法前面加上order_by方法,并且order_by方法中的字段就是我们要去重的字段数据

    官方文档中的下面这种写法
    Entry.objects.order_by('pub_date').distinct('pub_date')
    只适用于PostgreSQL数据库,mysql不支持distinct方法里面写字段

     

    (14)  字段的choices属性

     
    class Book(models.Model):
            ...
          # sex = models.CharField(max_length=12)
        sex_choices = ((1, '男性'),(0, '女性'))  #enum枚举 单选
        sex = models.IntegerField(choices=sex_choices, default=1)
    
    获取含有choices属性的字典数据方法
    ret = models.Book.objects.get(id=5)
    print(ret.sex)  # 1 获取到的是数据库中存储的字段数据
    print(ret.get_sex_display())  # 男性 -- 能够帮我们获取到该字段数据对应的choices指定的元祖中的这个数据对应的文本内容
        # sex_choices = ((1, '男性'), (0, '女性'))  # enum枚举 单选
        # sex = models.IntegerField(choices=sex_choices, default=1)
        # 比如拿sex这个字段来说,数据库中存的数据是1,表示男性,如果我想获取到男性这个字符串数据,直接通过模型类对象.get_sex_display()这个方法就能获取到,
    这个方法的语法是get_模型类属性名称_display()
     

    (15) auto_now_add和auto_now

     
    class ShowTime(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        brithday = models.DateTimeField(auto_now_add=True) #添加记录时,自动添加创建时间
        bday = models.DateTimeField(auto_now=True) #添加记录时,也能自动添加创建时间,并且更新记录时,自动更新为当前时间
    
    
    #models.DateTimeField(auto_now=True)中的auto_now=True对update方法没有效果
        # models.ShowTime.objects.all().update(
        #     name='chao2',
        # )
    
        #auto_now=True只有在使用save方法来进行更新动作时,才生效,才会自动更新修改时间
        ret = models.ShowTime.objects.get(id=1)
        ret.name = 'zhen'
        ret.save()
     

    关键字传参

     
    两种方式:
    方式1
    filter(id=5, publish='腾讯出版社')
    create(id=5, publish='腾讯出版社')
        ...
    
    方式2
    filter(**{'id':5, 'publish':'腾讯出版社'})
        ...
     

    基于双下划线的模糊查询

     
    # 值等于一个范围里的任意一个的对象
    models.Book.objects.filter(price__in=["11.9","99"])  # 针对decimal写字符串的形式
    models.Book.objects.filter(price2__in=[20, 18])  # 针对float或者int类型用数字
    
    # 大于查询: gt
    models.Book.objects.filter(price__gt=11.9)
    # 大于等于查询: gte
    models.Book.objects.filter(price__gte=11)
    
    小于查询: lt
    models.Book.objects.filter(price__lt=11.9)
    小于等于查询: lte
    models.Book.objects.filter(price__lte=11.9)
    
    范围查询: range
    models.Book.objects.filter(price__range=["11.9","15.9"])
    # 相当于sql的between and,大于等于100,小于等于200, 查询是小数的话要写成字符串
     

    针对字符串的操作:

     
    # 包含某些字符串的操作: contains
    models.Book.objects.filter(title__contains="的")
    Book.objects.filter(title__icontains="python") # 前面加i表明不区分大小写
    
    # 找到以某些字符串开头或者结尾的
    models.Book.objects.filter(title__startswith="看")
    Book.objects.filter(title__istartswith='p') # 前面加i表明不区分大小写
    
    Book.objects.filter(title__endswith="py") # 以什么结尾
    Book.objects.filter(title__iendswith='p') # iendswith  不区分大小写
     

    日期类型的数据操作

     
    # 以年份查找
    models.Book.objects.filter(pub_date__year=2019)
    # 以年月查找
    models.Book.objects.filter(pub_date__year=2019,pub_date__month=7) 
    # 以月查找
    models.Book.objects.filter(pub_date__month=7)
    
    # 查询某个字段为空的数据
    models.Book.objects.filter(title__isnull=True) #正规的
    models.Book.objects.filter(title=None)
     

    查看某个orm语句的原生sql语句方法

    print(models.Book.objects.filter(title__isnull=True).query)
  • 相关阅读:
    SPOJ SAMER08A
    SPOJ TRAFFICN
    CS Academy Set Subtraction
    CS Academy Bad Triplet
    CF Round 432 C. Five Dimensional Points
    CF Round 432 B. Arpa and an exam about geometry
    SPOJ INVCNT
    CS Academy Palindromic Tree
    身体训练
    简单瞎搞题
  • 原文地址:https://www.cnblogs.com/nihao2/p/12102696.html
Copyright © 2011-2022 走看看