zoukankan      html  css  js  c++  java
  • ORM:对象关系映射

    一、简单操作

    1. 定义:面向对象和关系型数据库的一种映射,通过操作对象的方式操作数据

    2. 对应关系:

      • 类对应数据表
      • 对象对应数据行(记录)
      • 属性对应字段
    3. 导入:from app01 import models

    4. 查:

      • models.Publisher.objects.all()
        • 查询所有的数据,queryset:对象列表
      • models.Publisher.objects.get(name='xxxx')
        • 对象,获取一个对象(有且唯一),获取不到或者获取到多个对象会报错
      • models.Publisher.objects.filter(name='xxxx')
        • 获取满足条件的所有的对象,queryset:对象列表
    5. 增:

      • models.Publisher.objects.create(name='xxx')
        • 新插入数据库的对象
      • obj = models.Publisher(name='xxx')
        • 存在在内存中的对象
      • obj.save()
        • 提交到数据库中,新增
    6. 删:

      • obj = models.Publisher.objects.get(pk=1)
        • obj.delete()
      • obj_list = models.Publisher.objects.filter(pk=1)
        • obj_list.delete()
    7. 改:

      • obj = models.Publisher.objects.get(pk=1)
      • obj.name = 'new name'
        • 在内存中修改对象的属性
      • obj.save()
        • 提交数据,保存到数据库中

    二、 字段

    1. 常用字段

      • AutoField:自增的整型字段,必填参数primary_key=True
        • 注意:一个model不能有两个AutoField字段
      • IntegerField:整数类型,数值的范围是 -2147483648 ~ 2147483647
      • CharField:字符类型,必须提供max_length参数,max_length表示字符的长度
      • DateField:日期类型,日期格式为YYYY-MM-DD,相当于Python中的datetime.date的实例
        • 参数:
          • auto_now_add=True:新增数据的时候会自动保存当前的时间
          • auto_now=True:新增、修改数据的时候会自动保存当前的时间
      • DatetimeField:日期时间类型,格式为YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime的实例
      • BooleanField:布尔值类型
      • TextField:文本类型
      • DecimalField:十进制小数
        • 参数:
          • max_digits:小数总长度
          • decimal_places:小数位总长度
    2. 自定义字段

      • 自定义一个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
      
      • 使用自定义char类型字段
      class Class(models.Model):
          id = models.AutoField(primary_key=True)
          title = models.CharField(max_length=25)
          # 使用自定义的char类型的字段
          cname = MyCharField(max_length=25)
      

    三、 字段参数

    1. null:数据库中字段是否可以为空
    2. default:数据库中字段的默认值
    3. primary_key:数据库中字段是否为主键
    4. db_index:数据库中字段是否可以建立索引
    5. unique:数据库中字段是否可以建立唯一索引
    6. blank:Admin中是否允许用户输入为空
    7. choices:Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
      • choices=((0, '女'), (1, '男') :可填写的内容和提示

    四、 Model Meta参数

    • 在表对于的类中写入一个类Meta

      class UserInfo(models.Model):
          nid = models.AutoField(primary_key=True)
          username = models.CharField(max_length=32)
       
          class Meta:
              # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
              db_table = "table_name"
              # admin中显示的表名称
              verbose_name = '个人信息'
              # verbose_name加s
              verbose_name_plural = '所有用户信息'
              # 联合索引 
              index_together = [
                  ("pub_date", "deadline"),  	 # 应为两个存在的字段
              ]
              # 联合唯一索引
              unique_together = (("driver", "restaurant"),)   # 应为两个存在的字段
      

    五、 ORM操作——必知必会13条

    1. all():查询所有结果,返回QuerySet对象
    2. get():返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误,返回单个对象
    3. filter():返回所有符合条件的对象,返回QuerySet对象
    4. exclude():返回所有不符合条件的对象,返回QuerySet对象
    5. values('字段'):拿到对象指定的字段和字段的值,返回的是一个字典序列,返回QuerySet对象
    6. values_list('字段'):拿到对象指定的字段的值,返回的是一个元组序列,返回QuerySet对象
    7. order_by():对查询结果排序,默认升序,字段前加负号则为降序,返回QuerySet对象
      • order_by('age','-pid'):先按age字段升序排列,再按pid字段降序排列
    8. reverse():对查询结果反向排序,只能对已经排序的QuerySet进行反转,返回QuerySet对象
    9. distinct():对查询结果进行去重,完全相同的内容才能去重,返回QuerySet对象
    10. count():计数,返回数据库中匹配查询的对象数量,返回数字
    11. first():返回第一条记录,即取第一个元素,没有返回None,返回单个对象
    12. last():返回最后一条记录,即取最后一个元素,没有返回None,返回单个对象
    13. exist():判断查询的数据是否存在,存在返回True,否则返回False,返回布尔值
    • 总结:

      # 返回的是queryset对象的
      all()    
      filter()
      exclude()
      values()  
      values_list() 
      order_by() 
      reverse() 
      distinct()
      # 返回的是单个对象的
      get() 
      first()
      last()
      # 返回的是数字的
      count()
      # 返回的是布尔值的
      exists()
      

    六、 单表查询的双下划线

    1. 条件判断,相当于SQL中的while
      • __gt:大于
        • ret = models.Person.objects.filter(pk__gt=1)
          • 获取pk大于1的
      • __lt:小于
        • ret = models.Person.objects.filter(pk__lt=3)
          • 获取pk小于3的
      • __gte:大于等于
        • ret = models.Person.objects.filter(pk__gte=1)
          • 获取pk大于等于1的
      • __lte:小于等于
        • ret = models.Person.objects.filter(pk__lte=3)
          • 获取pk小于等于3的
    2. __range:范围查询,相当于SQL的between...and...
      • ret = models.Person.objects.filter(pk__range=[1,3])
        • 获取pk范围是1到3的
    3. __in:成员判断
      • ret = models.Person.objects.filter(pk__in=[1,3])
        • 获取pk等于1、3的,相当于SQL的 in
      • ret = models.Person.objects.exclude(pk__in=[1,3])
        • 获取pk不等于1和3的,相当于SQL的 not in
    4. 模糊查询:相当于SQL的 like 和正则匹配
      • __contains:模糊查询
        • ret = models.Person.objects.filter(name__contains='A')
          • 获取name字段的值包含'A'的
      • __icontains:在contains的基础上,对条件中的字母大小写不敏感
        • ret = models.Person.objects.filter(name__icontains='A')
          • 获取name字段的值包含'A'或'a'的,忽略大小写
    5. 判断以...开头/结尾
      • __startswith:以...开头
        • ret = models.Person.objects.filter(name__startswith='A')
          • 获取name字段的值以'A'开头的
      • __istartswith:在startswith的基础上,对条件中的字母大小写不敏感
        • ret = models.Person.objects.filter(name__istartswith='A')
          • 获取name字段的值以'A'或'a'开头的,忽略大小写
      • __endswith:以...结尾
        • ret = models.Person.objects.filter(name__endswith='A')
          • 获取name字段的值以'A'结尾的
      • __iendswith:在endswith的基础上,对条件中的字母大小写不敏感
        • ret = models.Person.objects.filter(name__iendswith='A')
          • 获取name字段的值以'A'或'a'结尾的,忽略大小写
    6. __year:判断日期年份
      • ret = models.Person.objects.filter(birth__year='2019')
        • 获取birth字段的值的年份是2019的
      • __year只能筛选年份,如果要筛选年月日,使用contains:模糊查询
        • ret = models.Person.objects.filter(birth__contains='2018-06-24')
          • 获取birth字段的值是2018-06-24的
    7. __isnull:查询与null的项
      • __isnull = True:查询值是null的
        • ret = models.Person.objects.filter(phone__isnull=True)
          • 获取phone字段的值是null的
      • __isnull = False:查询值不是null的

    七、 ForeignKey操作

    1. 基于对象的查询

      • 正向查询,语法:对象.关联字段.字段
      book_obj = models.Book.objects.get(title='菊花怪大战MJJ')
      book_obj.pub
      book_obj.pub.name
      
      • 反向查询,语法:对象.表名_set.all(),表名即类名小写
        • 设置ForeignKey的参数:related_name,相当于替换了类名小写_set
      pub_obj = models.Publisher.objects.get(pk=1)
      # 没有指定related_name,使用类名小写_set
      pub_obj.book_set.all()
      # 指定related_name='books'
      pub_obj.books.all()
      
    2. 基于字段的查询

      • 正向查询,语法:关联字段__字段
      # 查询老男孩出版的书
      ret = models.Book.objects.filter(pub__name='老男孩出版社')
      
      • 反向查询,语法:表名__字段
        • 设置ForeignKey的参数:related_query_name,相当于替换了表名
      # 查询出版菊花怪大战MJJ的出版社
      # 没有指定related_name,使用类名的小写
      ret= models.Publisher.objects.filter(book__title='菊花怪大战MJJ')
      # related_name='books'
      ret= models.Publisher.objects.filter(books__title='菊花怪大战MJJ')
      # related_query_name='xxx'
      ret= models.Publisher.objects.filter(xxx__title='菊花怪大战MJJ')
      

    八、 多对多的操作

    1. 基于对象的查询

      • 正向查询,语法:对象.多对多字段.all()
      mjj = models.Author.objects.get(pk=1)
      mjj.books	  	# 关系管理对象
      mjj.books.all()
      
      • 反向查询,语法:对象.类名小写_set.all()
        • 设置related_name,相当于替换了类名小写_set
      book_obj = models.Book.objects.filter(title='桃花侠大战菊花怪').first()
      # 不指定related_name
      book_obj.author_set  	# 关系管理对象
      book_obj.author_set.all()
      # 指定related_name='authors'
      book_obj.authors  		# 关系管理对象
      book_obj.authors.all()
      
    2. 基于字段的查询

      • 正向查询,语法:多对多字段__字段
      ret = models.Author.objects.filter(books__title='菊花怪大战MJJ')
      
      • 反向查询,语法:类名小写__字段
        • 设置related_query_name,相当于替换了类名小写
      # 不指定related_name
      ret = models.Book.objects.filter(author__name='MJJ')
      # 指定related_name='authors'
      ret = models.Book.objects.filter(authors__name='MJJ')
      # 指定related_query_name='xxx'
      ret = models.Book.objects.filter(xxx__name='MJJ')
      
    3. 关系管理对象的方法

      • all():所关联的所有对象
      mjj = models.Author.objects.get(pk=1)
      mjj.books.all()
      
      • set():设置多对多关系
      # set()  [id,id]   [对象,对象]
      mjj.books.set([1,2])
      mjj.books.set(models.Book.objects.filter(pk__in=[1,2,3]))
      
      • add():添加多对多关系
      # add  (id,id)   (对象,对象)
      mjj.books.add(4,5)
      mjj.books.add(*models.Book.objects.filter(pk__in=[4,5]))
      
      • remove():删除多对多关系
      # remove (id,id)   (对象,对象)
      mjj.books.remove(4,5)
      mjj.books.remove(*models.Book.objects.filter(pk__in=[4,5]))
      
      • clear():清除所有多对多关系
      mjj.books.clear()
      
      • create():创建多对多关系
      obj = mjj.books.create(title='跟MJJ学前端',pub_id=1)
      
      book__obj = models.Book.objects.get(pk=1)
      obj = book__obj.authors.create(name='taibai')
      

    九、 聚合和分组

    1. 聚合

      • 内置函数:Max(最大值)、Min(最小值)、Avg(平均值)、Sum(求和)、Count(计数)
      from app01 import models
      from django.db.models import Max, Min, Avg, Sum, Count
      # 为聚合值指定名称,注意关键字传参要在位置传参后面
      ret = models.Book.objects.filter(pk__gt=3).aggregate(Max('price'),avg=Avg('price'))
      print(ret)
      
    2. 分组

      • 一般和聚合一起使用
      # 统计每一本书的作者个数,annotate:注释
      ret = models.Book.objects.annotate(count=Count('author')) 
      
      # 统计出每个出版社的最便宜的书的价格
      # 方式一
      ret = models.Publisher.objects.annotate(Min('book__price')).values()
      # 方式二:objects后面接values,就是按字段分组,相当于分组条件
      ret = models.Book.objects.values('pub_id').annotate(min=Min('price'))
      

    十、 F查询和Q查询

    1. F查询

      from django.db.models import F
      # 比较两个字段的值
      ret=models.Book.objects.filter(sale__gt=F('kucun'))
      
      # 只更新sale字段
      models.Book.objects.all().update(sale=100)
      
      # 取某个字段的值进行操作
      models.Book.objects.all().update(sale=F('sale')*2+10)
      
    2. Q查询

      • 条件符号:&(与)、|(或)、~(非)
      from django.db.models import Q
      ret = models.Book.objects.filter(~Q(Q(pk__gt=3) | Q(pk__lt=2)) & Q(price__gt=50))
      print(ret)
      

    十一、 事务

    • 使用try进行回滚时,必须把try写在with的外面,否则无法回滚

      from django.db import transaction
      
      try:
          with transaction.atomic():
              # 进行一系列的ORM操作
              models.Publisher.objects.create(name='xxxxx')
              models.Publisher.objects.create(name='xxx22')
      except Exception as e :
          print(e)
      

    十二、 其他操作设置

    1. Django ORM执行原生SQL

      # 执行原生SQL
      # 更高灵活度的方式执行原生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()
      
    2. Django终端打印SQL语句

      LOGGING = {
          'version': 1,
          'disable_existing_loggers': False,
          'handlers': {
              'console':{
                  'level':'DEBUG',
                  'class':'logging.StreamHandler',
              },
          },
          'loggers': {
              'django.db.backends': {
                  'handlers': ['console'],
                  'propagate': True,
                  'level':'DEBUG',
              },
          }
      }
      
    3. 在Python中脚本中调用Django环境

      • 在要执行的py文件中写入
      import os
      os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
      # orm_practice.settings表示当前项目的settings.py,orm_practice是当前项目名称
      import django
      django.setup()
      
      from app01 import models
      # 再继续写要执行的语句,例如
      books = models.Book.objects.all()
      print(books)
      
  • 相关阅读:
    mysql data type <----> java data type (数值)
    line number is important in Exceptions.
    dom4j 使用原生xpath 处理带命名空间的文档
    dom4j 通过 org.dom4j.XPath 设置命名空间来支持 带namespace 的 xpath
    dom4j 创建一个带命名空间的pom.xml 文件
    xml to xsd ; xsd to xml
    sax 动态切换 抓取感兴趣的内容(把element当做documnet 处理)
    d3.js <一>
    python学习进阶一
    Java *字格
  • 原文地址:https://www.cnblogs.com/zengyi1995/p/11171456.html
Copyright © 2011-2022 走看看