Django ORM 操作

Posted zhang-zi-yi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django ORM 操作相关的知识,希望对你有一定的参考价值。

ORM (object Relational Mapping)

对象和关系型数据库的一个映射    同过操作对象的方式操作数据库的内容
  1. 对应关系
    > 表
    对象
    > 记录 数据行
    属性 ___> 字段
  2. ORM的操作:
    1. 查询
      1. models.Publisher.objects.all() # 查询所有的数据 ——》 QuerySet 对象列表
      2. models.Publisher.objects.get() # 获取满足条件的一个对象 ——》 单独的对象
      3. models.Publisher.objects.filter() # 获取满足条件的所有对象 ——》对象列表
      4. models.Publisher.objects.all().order_by(‘id‘) # 排序 —— 》 对象列表
      5. pub_obj.pk ——》 主键
      6. pub_obj.name
      7. 外键
      1. book_obj.publisher ——》 关联的对象
      2. book_obj.publisher_id ——》从book表中获取关联对象的ID
      3. book_obj.publisher.name ——》 关联的对象的属性
      8. 多对多
      1. author_obj.books ——》 管理对象
      2. author_obj.books.all() ——》 关联的所有的对象 对象列表
      3. book_obj.author_set ——》管理对象、

    2. 增加
      1. models.Publisher.objects.create(name=‘xxx‘) ——》 对象
      2. 外键
      1. models.Book.objects.create(title=‘xxx‘,publisher=pub_obj)
      2. models.Book.objects.create(title=‘xxx‘,publisher_id=pub_obj.id)
      3. 多对多
      1. models.Author.objects.create(name=‘xxxx‘) ——》 author_obj
      2. author_obj.books.set([多个要关联对象的id,])
      3. author_obj.books.set([多个要关联对象,])

    3. 删除
      1. models.Author.objects.get(id=1).delete()
      2. models.Author.objects.filter(id=1).delete()

    4. 修改
      1. 1. pub_obj.name = ‘new_xxxx‘
      2. pub_obj.save()
      3. 外键
      1. book_obj.title = ‘xxxx‘
      2. book_obj.publisher = pub_obj 或者 book_obj.publisher_id = pub_obj .id
      3. book_obj.save()
      4. 多对多
      1. author_obj.name = ‘new_name‘
      2. author_obj.save()
      3. author_obj.books.set([多个要关联对象,]) author_obj.books.set([多个要关联对象的id,])

    具体的操作
    from app01 import models
    # 获取所有数据
    models.User.objects.all() # > QuerySet 对象列表
    # 获取单个对象 获取不到数据或者拿到多条数据就报错
    models.User.objects.get(name=‘alex‘,pwd=‘111‘) #
    > 对象
    # 获取满足条件的所有对象
    models.User.objects.filter(name=‘alex‘,pwd=‘111‘) # __> QuerySet 对象列表
    字段和字段的参数
    1.字段和字段的参数

     常用的:                            
    
     AutoField    #  自增字段       
         参数:
             primary_key=True   #  主键
    
     IntegerField  #  整数类型   
         参数:             
                blank=True   #  admin中显示 
    
     BooleanField   #  bool类型 
         参数:
                choices((1,‘男‘),(0,‘女‘)) 只能有两个值 
             0 为存储的值  男女为显示的内容
    
     CharField     #   varchar 类型    
         参数:       
                max_length=32  #  必填  最大长度
    
     TextField   #   文本类型 
    
     DateTimeField   #  时间类型     
         参数:
                 auto_new_add=True  #  新增时自动保存当前时间
             auto_new=True      #  修改时自动保存当前时间
    
     DecimalField  #   小数类型      
         参数:
                 max_digits=5   #  小数总长速度
             decimal_places=2  #  小数位长度 
        ForeignKey(‘表名‘,)   #    外键
    
        OneTuoOneField(‘表名‘,)  #   等同于外键关联自己
         参数:
                related_name=‘books‘,     #  用于反向查询 
                related_query_name=‘book‘
    
        ManyToManyField(‘表名‘,)           #   多对多  
         参数:
                related_name=‘books‘,      #  用于反向查询 
                related_query_name=‘book‘      #  用于反向查询 
    
        其他参数:
         db_column=‘usrname‘         #  修改数据库中的列名 显示
         verbose_name="用户名"       #  admin中文提示
         black=True      #  校验时可以为空
             null=True       #  存储时可以为空
             unique=true      #  字段唯一
             default=‘默认值‘   #  为空时提供默认值

    自定义 Char 类型
    class MyCharField(models.Field):
    """
    自定义的char类型的字段类
    """

        def __init__(self, max_length, *args, **kwargs):
            self.max_length = max_length
            super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs)
    
        def db_type(self, connection):
            """
            限定生成数据库表的字段类型为char,长度为max_length指定的值
            """
            return ‘char(%s)‘ % self.max_length
    
    使用:
        phone = MyCharField(max_length=11, )

    class Meta:
    # 写在model 类中

    class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "person"
            # admin中显示的表名称
            verbose_name = ‘个人信息‘
    
            # verbose_name加s
            verbose_name_plural = ‘所有用户信息‘
    
            ordering = (‘id‘,)
    
            # # 联合索引
            # index_together = [
            #     ("pub_date", "deadline"),  # 应为两个存在的字段
            # ]
            #
            # # 联合唯一索引
            # unique_together = (("driver", "restaurant"),)  # 应为两个存在的字段

    2.查询的方法(13个)
    返回结果是对象列表
    all()
    filter()
    exclude()
    order_by()
    reverse()
    values()
    values_list()
    distinct()

    返回结果是对象
    get()
    first()
    last()
    
    返回布尔值
    exists()
    
    返回数字
    count()

    建立 数据库查询 orm操作
    modle 表结构
    from django.db import models

    class MyCharField(models.Field):
        """
        自定义的char类型的字段类
        """
    
        def __init__(self, max_length, *args, **kwargs):
            self.max_length = max_length
            super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs)
    
        def db_type(self, connection):
            """
            限定生成数据库表的字段类型为char,长度为max_length指定的值
            """
            return ‘char(%s)‘ % self.max_length
    
    
    class Person(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32, db_column=‘username‘, verbose_name=‘姓名‘)
        age = models.IntegerField(null=True, blank=True, verbose_name=‘年龄‘)
        # birth = models.DateTimeField(auto_now_add=True)    # 新增的时候保存当前的时间
        birth = models.DateTimeField(auto_now=True)  # 每次修改的时候保存当前的时间
        phone = MyCharField(max_length=11, )
        gender = models.BooleanField(choices=((0, ‘男‘), (1, ‘女‘)))
    
        def __str__(self):
            return "<Person object: {}-{}>".format(self.pk, self.name)
    
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "person"
            # admin中显示的表名称
            verbose_name = ‘个人信息‘
    
            # verbose_name加s
            verbose_name_plural = ‘所有用户信息‘
    
            ordering = (‘id‘,)
    
    class Publisher(models.Model):
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)  # 000.00    999.99
        sale = models.IntegerField()
        kucun = models.IntegerField()
        publisher = models.ForeignKey(‘Publisher‘, related_name=‘books‘, related_query_name=‘book‘, null=True)
    
        def __str__(self):
            return self.title + str(self.pk)
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        books = models.ManyToManyField(‘Book‘,)

    在setting 中配置 查看配置 显示查询语句
    import django
    django.setup()

    from app01 import models
    
    # all()   获取所有的数据  对象列表
    ret = models.Person.objects.all()
    
    # filter()   获取所有满足条件的所有对象    对象列表
    ret = models.Person.objects.filter(id=1)
    
    # get()     获取一个对象  没有或者是多个的时候报错
    ret = models.Person.objects.get(id=1)
    
    # exclude  获取不满足条件的所有对象  对象列表
    ret = models.Person.objects.exclude(id=1)
    
    
    # values  获取对象的字段名和值    [ {},{} ]
    # 不指定字段名  获取所有字段的名和值
    # 指定字段名    获取指定字段的名和值
    ret = models.Person.objects.all().values(‘name‘,‘id‘)
    # for i in ret:
    #     print(i,type(i))
    
    # values_list  获取对象的值    [ (),() ]
    # 不指定字段名  获取所有字段的值
    # 指定字段名    获取指定字段值
    ret = models.Person.objects.all().values_list(‘id‘,‘name‘)
    # for i in ret:
    #     print(i,type(i))
    
    # order_by 排序 默认升序  加- 降序  指定多个进行排序
    ret = models.Person.objects.all().order_by(‘age‘,‘id‘)
    
    # reverse() 给已经排好序的结果倒叙排序
    ret = models.Person.objects.all().order_by(‘age‘,‘id‘).reverse()
    
    ret = models.Person.objects.all().reverse()
    
    
    # distinct()  去重
    
    # count   计数
    ret = models.Person.objects.all().count()
    
    # first()  last   取第一个 最后一个对象
    ret = models.Person.objects.filter(id=100).first()
    
    # exists()  判断数据是否存在
    ret = models.Person.objects.filter(id=1).exists()

    3.单表的双下划线
    import os

    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
    import django
    
    django.setup()
    
    from app01 import models
    
    ret = models.Person.objects.filter(id=1)
    ret = models.Person.objects.filter(id__gt=1)  # greater than
    ret = models.Person.objects.filter(id__gte=1)  # greater than equal
    ret = models.Person.objects.filter(id__lt=3)  # less than
    ret = models.Person.objects.filter(id__lte=3)  # less than equal
    
    ret = models.Person.objects.filter(id__gt=1, id__lt=3)
    ret = models.Person.objects.filter(id__range=[1, 3])  # 范围  左右都包含
    ret = models.Person.objects.filter(id__in=[1, 3])  #
    
    ret = models.Person.objects.filter(name__contains=‘alex‘)  # 包含   like
    ret = models.Person.objects.filter(name__icontains=‘alex‘)  # 包含   like
    
    ret = models.Person.objects.filter(name__startswith=‘a‘)  # 以什么开头
    ret = models.Person.objects.filter(name__istartswith=‘a‘)  # 以什么开头  忽略大小写
    
    ret = models.Person.objects.filter(name__endswith=‘x‘)  # 以什么结尾
    ret = models.Person.objects.filter(name__iendswith=‘X‘)  # 以什么结尾  忽略大小写
    
    ret = models.Person.objects.filter(birth__year=2018)
    ret = models.Person.objects.filter(birth__contains=‘2018-12‘)

    4.外键的操作
    # 基于对象的查询
    # 正向 有外键的一侧 查关联的对象
    book_obj = models.Book.objects.get(id=1)

     book_obj.publisher    关联的对象
    # print(book_obj.publisher)     # 关联的对象
    # print(book_obj.publisher_id)  # 关联的对象的id
    # print(book_obj.publisher.id)  # 关联的对象的id
    
    # 反向查询   被关联的对象  查有外键的一侧
    # pub_obj = models.Publisher.objects.get(id=1)
    # print(pub_obj.name)
    
     不指定related_name
    
         pub_obj.book_set     管理对象  
    
         pub_obj.book_set.all()   
    
         指定related_name = ‘books’    
    
         pub_obj.books    管理对象
    # 不指定 related_name=‘books‘
    # print(pub_obj.book_set,type(pub_obj.book_set))
    # print(pub_obj.book_set.all())
    
    # 指定related_name=‘books‘
    # print(pub_obj.books,type(pub_obj.books))
    # print(pub_obj.books.all())
    
    # 基于字段的查询
    
    # ret = models.Book.objects.filter(publisher__name=‘老男孩出版社‘)
    
    # 不指定related_name
    # ret = models.Publisher.objects.filter(book__title=‘太亮教开车‘)
    
    # 指定related_name
    # ret = models.Publisher.objects.filter(books__title=‘太亮教开车‘)
    
    # 指定related_query_name=‘book‘
    # ret = models.Publisher.objects.filter(book__title=‘太亮教开车‘)
    
    
    # 外键字段可以为null 才有remove和clear  只能写对象
    pub_obj = models.Publisher.objects.get(id=1)
    # pub_obj.books.remove(models.Book.objects.get(id=1))
    # pub_obj.books.clear()
    
    pub_obj.books.create(title=‘太亮的产后护理‘)

    多对多的操作
    import os
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
    import django
    django.setup()
    from app01 import models

    # 基于对象的查询
    # 正向
    author_obj = models.Author.objects.get(id=2)
    #
    # print(author_obj.books,type(author_obj.books))
    # print(author_obj.books.all())
    
    # 反向
    book_obj = models.Book.objects.get(id=1)
    
    # 不指定related_name=‘authors‘
    # print(book_obj.author_set.all())
    
    # 指定related_name=‘authors‘
    # print(book_obj.authors.all())
    
    
    # set 设置多对多关系
    # author_obj.books.set([])
    # author_obj.books.set([1,2,3])   # 要关联对象的ID  [ 对象的id,对象的id]
    # author_obj.books.set(models.Book.objects.all())   # 要关联对象  [ 对象,对象]
    
    
    # add 添加多对多的关系
    # author_obj.books.add(1)  # 要关联对象的ID
    # author_obj.books.add(models.Book.objects.get(id=2))  # 要关联对象
    
    # remove()  删除多对多的关系
    
    # author_obj.books.remove(1)  # 要关联对象的id
    # author_obj.books.remove(models.Book.objects.get(id=2))  # 要关联对象
    
    # clear()  # 清空当前对象的多对多的关系
    # author_obj.books.clear()
    
    # create()
    # author_obj.books.create(title=‘太亮教抛光‘,)
    
    # update() 更新字段
    # author_obj.books.update(title=‘太亮教抛光‘,)
    
    book_obj.authors.create(name=‘alex‘)

    聚合 和分组
    Max, Min, Sum, Avg, Count
    mport os

    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
    import django
    
    django.setup()
    
    from app01 import models
    
    from django.db.models import Max, Min, Sum, Avg, Count
    
    ret = models.Book.objects.aggregate(max=Max(‘price‘))  # { }
    
    # 统计每一本书的作者个数
    ret = models.Book.objects.all().annotate(count=Count(‘author‘)).values(‘count‘)
    
    # 统计出每个出版社买的最便宜的书的价格
    # 方法一
    ret = models.Publisher.objects.all().annotate(Min(‘book__price‘)).values()
    # for i in ret:
    #     print(i)
    
    # 方法二
    ret = models.Book.objects.values(‘publisher__name‘).annotate(min=Min(‘price‘)).values(‘min‘)
    # for i in ret:
    #     print(i)
    
    
    # 统计不止一个作者的图书
    ret = models.Book.objects.annotate(count=Count(‘author‘)).filter(count__gt=1)
    ret = models.Book.objects.annotate(count=Count(‘author‘)).order_by(‘-count‘)
    print(ret)
    
    # 查询各个作者出的书的总价格
    ret = models.Author.objects.annotate(Sum(‘books__price‘)).values()
    for i in ret:
        print(i)

    F 和 Q
    import os

    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
    import django
    
    django.setup()
    
    from app01 import models
    from django.db.models import F
    
    # ret= models.Book.objects.filter(kucun__gt=F(‘sale‘)).values()
    # for i in ret:
    #     print(i)
    # models.Book.objects.all().update(sale=F(‘sale‘)*2)
    
    
    # obj = models.Book.objects.filter(id=1).first()
    #
    # obj.sale = 60
    # obj.save()
    
    from django.db.models import Q
    
    ret = models.Book.objects.filter(Q(~Q(id__lt=3) | Q(id__gt=5))&Q(id__lt=4))
    print(ret)

    事物
    import os

    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
    import django
    
    django.setup()
    
    from app01 import models
    
    from django.db import transaction
    
    try:
        with transaction.atomic():
            models.Publisher.objects.create(name=‘新华出版社1‘)
            int(‘aaa‘)
            models.Publisher.objects.create(name=‘新华出版社2‘)
            models.Publisher.objects.create(name=‘新华出版社2‘)
    except Exception as e:
            print(e)











































































以上是关于Django ORM 操作的主要内容,如果未能解决你的问题,请参考以下文章

Django---ORM操作大全

Django之ORM

Django-ORM操作数据库无数据问题

Django models ORM基础操作--白话聊Django系列

Django之ORM

Django orm操作