ORM

ORM是什么

  ORM实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于数据库,通过简单的配置就可以轻松更换数据库,这减轻了开发人员的工作量. 

  对象和关系型数据库的映射

必会13条:

1. 返回对象列表的
all()   Book.objects.all()
filter()
exclude()
order_by()
reverse()
distinct()
values() {}
values_list() ()

2. 获取对象的
get()
first()
last()

3. 返回数字
count()

4. 返回布尔值
exists()

单表双下: 

 

基于双下划线的模糊查询,单表中双下表示比较这个字段.

   Book.objects.filter(price__in=[100,200,300]) #price在这个列表内的
     Book.objects.filter(price__gt=100)  #price大于100
     Book.objects.filter(price__lt=100)   ##price小于100
     Book.objects.filter(price__range=[100,200])  #pirce在100到200之间
     Book.objects.filter(title__contains="python") # 模糊查询titile包含ptyhon,区分大小写
     Book.objects.filter(title__icontains="python")  # 不区分大小写
     Book.objects.filter(title__startswith="py")   #title以py开头
     Book.objects.filter(pub_date__year=2012)  #pub_data是2012年的
     Book.objects.filter(pub_date__year__gt=2012) #pub_data是2012年后的

id__gt
id__lt
id__lte
id__gte

id__in=[]
id__range=[1,4]

contains= ''
icontains= ''

startswith = ''
istartswith = ''
endswith = ''
iendswith = ''

isnull = True


__year

 

FK外键

  publish=models.ForeignKey(to="Publish",to_field="nid",relate_name="xxx",on_delete=models.CASCADE)

m2m 多对多

 

  authors=models.ManyToManyField(to='Author')     #authors不是一个真实的字段.只是ORM层面建立的一个多对多关系.用authors关联作者表.

author_obj.books --》管理对象
author_obj.books.add()
author_obj.books.remove()
author_obj.books.clear()
author_obj.books.set() []
author_obj.books.create()

book_obj.authors --》管理对象

跨表双下

正相查

反向查

聚合

   #查书的平均价格  

  Book.objects.all().aggregate(AVG("price"))  

  #查书的最高价,最低价
  Book.objects.aggregate( Max('price'), Min('price'))

分组

  跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询

Employee.objects.values("dep").annotate(avg=AVG("salary"))
筛选出部门 annoteta是按前面的内容分组

# 查询每一个作者的名字以及出版书籍的最高价格
Author.objects.annotate(max_price=Max("book__price")).values("name","max_price")

# 查询96年以后出生的每一个作者的名字以及出版书籍的最高价格
Author.objects.filter(birthday__year__gt=1996).annotate(max_price=Max("book__price")).values("name","max_price")

# 查询不止一个作者的书籍名称以及关联的作者个数
Book.objects.all().annotate(c=Count("authors")).filter(c__gt=1).values("title","c")

# 查询部门1的每一个销售的名字以及今天对应的成单量
Userinfo.objects.filter(depart_id=1).filter(customer__deal_date=now).annotate(c=Count("customers")).values("name","c")

统计每一本书的作者个数
ret=Book.objects.annotate(authorsNum=Count('authors__name')

   Book.objects.filter(commnetNum__lt=F('keepNum'))  #查评论数小于keepNum的
  Book.objects.all().update(price=F("price")+30)  #所有书的价格加30

Q: 查询条件or的关系

用|分割不同的Q查询条件,
查询作者名称是max或ding的书
bookList=Book.objects.filter(Q(authors__name="max")|Q(authors__name="ding"))


  Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询
  bookList=Book.objects.filter(Q(authors__name="max") & ~Q(publishDate__year=2017)).values_list("title")

  Q 对象,它必须位于所有关键字参数的前面。
  Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),title__icontains="python")

2种查询方式

  1. 基于对象查询  对应sql的子查询

    正向:  按字段查

        book_obj.authors.all()

    反向: 小写表名_set/related_name

       author_obj.book_set.all()  

  2. 基于双下划线查询  对应sql的join连表查询

    正向:  按字段

         Book.objects.filter(title="python").values("publish__name")     #查python的出版社名称

    反向: 按小写表名
       Author.objects.filter(name__startswith="a").values("book__title")   #查姓名是a开头的作者有哪些书

中介模型:

  M2M类型自动生成第三张表,但是第三张不可修改, 如果想修改第三张表例如添加字段怎么办?  用中介模型, 既可以自定义第三张表字段 也可以继续使用orm的语法.

    class Student(models.Model):
            name = models.CharField( max_length=32)
            courses=models.ManyToManyField("Courses",through="Score") # 告诉djaong用Source表做第三张表
                                
       class Course(models.Model):
            name = models.CharField( max_length=32)    
                                                                
       class Score(models.Model):
             student=models.ForeignKey("Student")
             course=models.ForeignKey("Course")
             score=models.IntegerField()

使用ORM步骤:

step1 定义模型类:


class Book(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=32,verbose_name="书籍名称") # CharField需要max_length参数来指定VARCHAR数据库字段的大小 state=models.BooleanField() pub_date=models.DateField() price=models.DecimalField(max_digits=8,decimal_places=2) publish=models.CharField(max_length=32) def __str__(self): return self.title class Meta: app_label="APP01" db_table="appBook" # 自定义表名,默认显示app_小写类名 unique_together=["title","price"] #设置联合唯一 verbose_name="书籍" #设置admin中表显示名称 ordering=["price"] #设置这个表以price字段排序

  模型类常用字段:

<1> CharField
                        字符串字段, 用于较短的字符串.
                <2> IntegerField
                        用于保存整数.
 
                <3> FloatField
                        浮点数. 必须提供两个参数max_digits总位数  和decimal_places小数位数: e.gmodels.FloatField(..., max_digits=5, decimal_places=2)                         
                 
                <4> AutoField:自增 整型
                        系统会自动添加一个名为id的自增的整型主键字段到你的 model.
                        默认名为id,可以修改名称:自定义一个主键:my_id=models.AutoField(primary_key=True)                    
                 
                <5> BooleanField
                        A true/false field. admin 用 checkbox 来表示此类字段.
                 
                <6> TextField
                        一个容量很大的文本字段.
                        admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
                 
                <7> EmailField
                        一个带有检查Email合法性的 CharField,不接受 maxlength 参数.
                 
                <8> DateField
                
                        一个日期字段. 共有下列额外的可选参数:
                        Argument    描述
                        auto_now    每次修改时自动修改为当前时间. 通常用于表示 "last-modified" 时间戳.
                        auto_now_add  对象创建时自动添加到当前时间
                        (仅仅在admin中有意义...)
                 
                <9> DateTimeField
                         一个日期时间字段. 类似 DateField 支持同样的附加选项.
                 
                <10> ImageField
                        类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
                        如果提供这两个参数,则图片将按提供的高度和宽度规格保存.                                
                           
           
           字段的参数:
                    (1)null 默认为False。
                       null=True 该字段不必填,是数据库的限制. 
                       
                       blank  默认为False。
                             blank=True  admin中不必填,是admin的限制. 通常null=True和blank=True一起设置                                     
                            要注意,blank与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
                            如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
                         
                    (2)default
                     
                        字段默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。
                     
                    (3)primary_key                     
                        如果为True,那么这个字段就是模型的主键。如果没指定字段的primary_key=True,
                        Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
                        否则没必要设置任何一个字段的primary_key=True。
                     
                    (4)unique 设置唯一,例如订单号设置为unique                     
                        如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
                     
                    (5)choices
                            由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是下拉框,下拉框的选项就是choices 中的选项。
model常用字段和参数

step2.在settings中配置:

                    DATABASES = {
                        'default': {
                            'ENGINE': 'django.db.backends.mysql',
                            'NAME':'bms',           # 要连接的数据库,连接前需要创建好
                            'USER':'root',        # 连接数据库的用户名
                            'PASSWORD':'',        # 连接数据库的密码
                            'HOST':'127.0.0.1',       # 连接主机,默认本级
                            'PORT':3306            #  端口 默认3306
                        },
                        
                        'app01': {     #指定app01的配置,没有指定用default
                            'ENGINE': 'django.db.backends.mysql',
                            'NAME':'bms',           # 要连接的数据库,连接前需要创建好
                            'USER':'root',        # 连接数据库的用户名
                            'PASSWORD':'',        # 连接数据库的密码
                            'HOST':'127.0.0.1',       # 连接主机,默认本级
                            'PORT':3306            #  端口 默认3306
                        },                        
                    }

step3 项目名文件下的__init__,在里面写入:

          import pymysql
            pymysql.install_as_MySQLdb()
            # 因为django默认驱动是MySQLdb,可是MySQLdb 对于py3支持不好,所以我们需要的驱动是PyMySQL.

step4 通过迁移的命令创建数据表:

          python manage.py makemigrations
          python manage.py migrate        

step5 如果想打印orm转换过程中的sql,在settings中配置:

      LOGGING = {
                        'version': 1,
                        'disable_existing_loggers': False,
                        'handlers': {
                            'console':{
                                'level':'DEBUG',
                                'class':'logging.StreamHandler',
                            },
                        },
                        'loggers': {
                            'django.db.backends': {
                                'handlers': ['console'],
                                'propagate': True,
                                'level':'DEBUG',
                            },
                        }
                    } 

添加记录举例:

    #方法1,模型类的create
                book_obj=Book.objects.create(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12")
     #方法2,创建类对象再save()
                book_obj=Book(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12")
                book_obj.save()
原文地址:https://www.cnblogs.com/dingyunfeng/p/10506714.html