Django ORM 模型

目录

ORM介绍

Django ORM的一些主要特性:

ORM的优势

ORM的劣势

Django项目使用MySQL数据库

Model

字段

字段类型

字段参数

ORM操作

基本操作

查询操作:

单表查询之神奇的双下划

外键操作

 正向查找

反向操作

对象查找

ManyToManyField

聚合查询和分组查询

聚合

分组

 F查询和Q查询

 F查询

Q查询

总结

ORM介绍

        Django ORM (Object-Relational Mapping)是Django框架中用于与数据库进行交互的工具。它提供了一种方便的方式来执行数据库操作,而无需直接编写SQL语句。

        Django ORM的核心理念是将数据库中的表映射为Python类,将表中的行映射为类的实例。开发者可以通过操作这些类和实例来执行数据库的增删改查操作。

        ORM在业务逻辑层和数据库层之间充当了桥梁的作用。

Django ORM的一些主要特性:

  1. 数据模型定义:使用Django ORM,开发者可以通过定义Python类来描述数据库中的表结构。类的属性通常会映射到表的字段,而类的方法则用于定义数据库操作。

  2. 数据库迁移:Django ORM提供了强大的数据库迁移工具,可以轻松地在开发过程中对数据库进行版本管理。开发者可以通过迁移命令自动将数据模型更新到最新版本,而无需手动编写SQL语句。

  3. 查询语句生成:通过使用Django ORM提供的查询API,开发者可以使用Python代码来生成SQL查询语句。这种方式比手动编写SQL语句更安全、更易读、更易维护。

  4. 查询优化:Django ORM提供了一些查询优化的机制,如查询缓存和惰性查询等。这些机制可以帮助开发者提高查询性能,减少与数据库的交互次数。

  5. 事务管理:Django ORM支持事务的原子操作,开发者可以使用事务来确保一组数据库操作要么全部成功,要么全部失败。这样可以保证数据的一致性和完整性。

ORM的优势

        ORM解决的主要问题是对象和关系的映射。它通常将一个类和一张表一一对应,类的每个实例对应表 中的一条记录,类的每个属性对应表中的每个字段。

        ORM提供了对数据库的映射,不用直接编写SQL代码,只需操作对象就能对数据库操作数据。 让软件开发人员专注于业务逻辑的处理,提高了开发效率。

        

ORM的劣势

        ORM的缺点是会在一定程度上牺牲程序的执行效率。

        ORM的操作是有限的,也就是ORM定义好的操作是可以完成的,一些复杂的查询操作是完成不了。

        ORM用多了SQL语句就不会写了,关系数据库相关技能退化...

Django项目使用MySQL数据库

        要在Django项目中使用MySQL数据库,需要在项目的设置文件(settings.py)中进行配置。

pip install mysqlclient

        接下来,在设置文件的DATABASES部分进行配置。您需要提供数据库的名称、用户名、密码、主机和端口等信息。将以下代码添加到设置文件中:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '<database_name>',
        'USER': '<username>',
        'PASSWORD': '<password>',
        'HOST': '<host>',
        'PORT': '<port>',
    }
}

        请确保将<database_name><username><password><host><port>替换为实际的数据库信息。分别是数据库名字,用户名称,数据库密码,ip地址,端口号默认3306

在与Django项目同名的目录下的init.py文件中写如下代码,告诉Django使用pymysql模块连接

import pymysql
pymysql.install_as_MySQLdb()

最后通过两条数据库迁移命令即可在指定的数据库中创建表 : 

python3 manage.py makemigrations
python3 manage.py migrate

确保配置文件中的INSTALLED_APPS中写入我们创建的app名称 

INSTALLED_APPS = [

    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "user_app"
]

如果想打印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',
        },
    }
}

 在终端执行脚本:

import os
if __name__ == __'main'__:
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()
    from app01 import models
    books = models.Book.objects.all()
    print(books)

 Django支持MySQL5.5及更高版本。

Model

        在Django中model是数据的单一、明确的信息来源。它包含了你存储的数据的重要字段和行为。通 常,一个模型(model)映射到一个数据库表。

  • 每个模型都是一个Python类,它是django.db.models.Model的子类。
  • 模型的每个属性都代表一个数据库字段。

字段

        常用字段

        AutoField

        自增的整形字段,必填参数primary_key=True,则成为数据库的主键。无该字段时,django自动创 建。

        一个model不能有两个AutoField字段。

        IntegerField

        一个整数类型。数值的范围是 -2147483648 ~ 2147483647。

        CharField

        字符类型,必须提供max_length参数。max_length表示字符的长度。

       DateField 

        日期类型,日期格式为YYYY-MM-DD,相当于Python中的datetime.date的实例。

        参数

        auto_now:每次修改时修改为当前日期时间。

        auto_now_add:新创建对象时自动添加当前日期时间。

        auto_now和auto_now_add和default参数是互斥的,不能同时设置。

字段类型

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)
- 二进制类型

字段参数

null 数据库中字段是否可以为空

db_column 数据库中字段的列名

default 数据库中字段的默认值

primary_key 数据库中字段是否为主键

db_index 数据库中字段是否可以建立索引

unique 数据库中字段是否可以建立唯一索引

unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引

unique_for_month 数据库中字段【月】部分是否可以建立唯一索引

unique_for_year 数据库中字段【年】部分是否可以建立唯一索引

verbose_name Admin中显示的字段名称

blank Admin中是否允许用户输入为空

editable Admin中是否可以编辑

help_text Admin中该字段的提示信息

choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作

如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)

error_messages 

自定义错误信息(字典类型),从而定制想要显示的错误信息;

字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date

        如:{'null': "不能为空.", 'invalid': '格式错误'}

validators      自定义错误验证(列表类型),从而定制想要的验证规则

from django.core.validators import RegexValidator

from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\

MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator

    如:

        test = models.CharField(

        max_length=32,

        error_messages={

            'c1': '优先错信息1', 'c2': '优先错信息2','c3': '优先错信息3',

        }, 

            validators=[

                RegexValidator(regex='root_\d+', message='错误了',code='c1'),

                RegexValidator(regex='root_112233\d+', message='又错误了',code='c2'),

                EmailValidator(message='又错误了', code='c3'), ]

        )

ForeignKey(ForeignObject) # ForeignObject(RelatedField)

to, # 要进行关联的表名

to_field=None, # 要关联的表中的字段名称

on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为

- models.CASCADE,删除关联数据,与之关联也删除

- models.DO_NOTHING,删除关联数据,引发错误IntegrityError

- models.PROTECT,删除关联数据,引发错误ProtectedError

- models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)

- models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)

- models.SET,删除关联数据,

a. 与之关联的值设置为指定值,设置:models.SET(值)

b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

    def func():

        return 10

    class MyModel(models.Model):

        user = models.ForeignKey(

        to="User",
        
        to_field="id"

        on_delete=models.SET(func),)

related_name=None,  # 反向操作时,使用的字段名,用于代替 【表名_set】

    如: obj.表名_set.all()

related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 

    如:

models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')

limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:

                       # 如:

        - limit_choices_to={'nid__gt': 5}

        - limit_choices_to=lambda : {'nid__gt': 5}

        from django.db.models import Q

        - limit_choices_to=Q(nid__gt=10)

        - limit_choices_to=Q(nid=8) | Q(nid__gt=10)

        - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')

db_constraint=True # 是否在数据库中创建外键约束

parent_link=False # 在Admin中是否显示关联数据

OneToOneField(ForeignKey)

to, # 要进行关联的表名

to_field=None   # 要关联的表中的字段名称

on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为

                ###### 对于一对一 ######

                # 1. 一对一其实就是 一对多 + 唯一索引

                # 2.当两个类之间有继承关系时,默认会创建一个一对一字段

                # 如下会在A表中额外增加一个c_ptr_id列且唯一:

                    class C(models.Model):

                        nid = models.AutoField(primary_key=True)

                        part = models.CharField(max_length=12)

                    class A(C):

                        id = models.AutoField(primary_key=True)

                        code = models.CharField(max_length=1)

ManyToManyField(RelatedField)

to, # 要进行关联的表名

related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】

如: obj.表名_set.all()

related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】

如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')

limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:

如:

- limit_choices_to={'nid__gt': 5}

- limit_choices_to=lambda : {'nid__gt': 5}

                from django.db.models import Q

                - limit_choices_to=Q(nid__gt=10)

                - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
    
                - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10))&Q(caption='root')

symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段

                # 做如下操作时,不同的symmetrical会有不同的可选字段

                    models.BB.objects.filter(...)

                # 可选字段有:code, id, m1

                    class BB(models.Model):

                    code = models.CharField(max_length=12)

                    m1 = models.ManyToManyField('self',symmetrical=True)

                # 可选字段有: bb, code, id, m1

                    class BB(models.Model):

                    code = models.CharField(max_length=12)

                    m1 = models.ManyToManyField('self',symmetrical=False)


through=None, # 自定义第三张表时,使用字段用于指定关系表

through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表

        from django.db import models

        class Person(models.Model):

            name = models.CharField(max_length=50)

        class Group(models.Model):

            name = models.CharField(max_length=128)

            members = models.ManyToManyField(

                Person,

                through='Membership',

                through_fields=('group', 'person'),

            )

         class Membership(models.Model):

            group = models.ForeignKey(Group,on_delete=models.CASCADE)

            person = models.ForeignKey(Person,on_delete=models.CASCADE)
        
            inviter = models.ForeignKey(

                Person,

                on_delete=models.CASCADE,

                related_name="membership_invites",

           )

            invite_reason = models.CharField(max_length=64)

db_constraint=True, # 是否在数据库中创建外键约束

db_table=None, # 默认创建第三张表时,数据库中表的名称

        id字段是自动添加的,如果你想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 即可。如果 Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列。

        本示例中的CREATE TABLE SQL使用PostgreSQL语法进行格式化,但值得注意的是,Django会根据配置文件中 指定的数据库类型来生成相应的SQL语句。

ORM操作

        QuerySet数据类型介绍:

        QuerySet与惰性机制:所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对 象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。

        QuerySet特点:

         可迭代的

         可切片

基本操作


# 增
models.Tb1.objects.create(c1 ='xx', c2 ='oo') # 增加一条数据,可以接受字典类型数据
**kwargs

obj = models.Tb1(c1 = 'xx' , c2 = 'oo')
obj.save()

# 查
models.Tb1.objects.get(id= 123) # 获取单条数据,不存在则报错(不建议)
models.Tb1.objects.all() # 获取全部
models.Tb1.objects.filter``(name='seven') # 获取指定条件的数据
models.Tb1.objects.exclude(name='seven') # 去除指定条件的数据

# 删
# models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据

# 改
models.Tb1.objects.filter(name = 'seven' ).update(gender = '0') # 将指定条件的数据更新,均支 
#  持 **kwargs

obj = models.Tb1.objects.get(id = 1)
obj.c1 = '111'
obj.save() # 修改单条数据

查询操作:

1. all(): 查询所有结果
2. get(**kwargs):  返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
3. filter(**kwargs): 包含与所给筛选条件相匹配的对象
4. exclude(**kwargs): 包含与所给筛选条件不匹配的对象
5. values(*field): 返回一个ValueQuerySet,得到的是一个可迭代的字典序列,不是一系列model的实例化对象
6. values_list(*field): 与values()非常相似,返回的是一个元组序列,values返回的是一个字典序列
7. order_by(*field): 对查询结果排序
8. reverse(): 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。
9. distinct(): 从返回结果中剔除重复记录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)
10. count(): 返回数据库中匹配查询(QuerySet)的对象数量。
11. first(): 返回第一条记录
12. last(): 返回最后一条记录
13. exists(): 如果QuerySet包含数据,就返回True,否则返回False

返回QuerySet对象的方法有:

        all()        filter()       exclude()      order_by()      reverse()       distinct()

特殊的QuerySe

        values() 返回一个可迭代的字典序列     values_list() 返回一个可迭代的元组序列

返回具体对象的

        get()            first()        last()

返回布尔值的方法有:

        exists()

返回数字的方法有

        count()

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

1 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
2 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
3 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
4 models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的
5 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
6 models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and
7 类似的还有:startswith,istartswith, endswith, iendswith
8 date字段还可以:
9 models.Class.objects.filter(first_day__year=2020)
  1. 用于字段查询:双下划线可以用于指定字段的特定属性或条件。例如,field__exact表示字段的精确匹配,field__gt表示字段的大于某个值的条件,field__contains表示字段包含某个值的条件等。

  2. 用于关联查询:双下划线可以用于跨表查询,通过指定关联字段的名称和相关属性来实现。例如,related_model__field表示查询相关模型的指定字段。

  3. 用于日期和时间查询:双下划线可以用于对日期和时间字段进行查询。例如,date_field__year表示查询日期字段的年份,time_field__hour表示查询时间字段的小时等。

  4. 用于查询聚合和注解:双下划线可以用于对查询结果进行聚合操作或添加注解。例如,annotate_field__sum表示对某个字段进行求和操作。

外键操作

   正向查找

   对象查找(跨表)        

 语法:
 对象.关联字段.字段


#  示例
 book_obj = models.Book.objects.first() # 第一本书对象
 print(book_obj.publisher) # 得到这本书关联的出版社对象
 print(book_obj.publisher.name) # 得到出版社对象的名称

  字段查找(跨表)

语法:
关联字段__字段


# 示例
print(models.Book.objects.values_list("publisher__name"))

反向操作

对象查找

语法:
obj.表名_set

# 示例
publisher_obj = models.Publisher.objects.first() # 找到第一个出版社对象
books = publisher_obj.book_set.all() # 找到第一个出版社出版的所有书
titles = books.values_list("title") # 找到第一个出版社出版的所有书的书名

字段查找

语法:
表名___字段

# 示例
titles = models.Publisher.objects.values_list("book__title")

ManyToManyField

class RelatedManager

        "关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。

它存在于下面两种情况:

        1. 外键关系的反向查询

        2. 多对多关联关系

简单来说就是当 点后面的对象 可能存在多个的时候就可以使用以下的方法。

方法

create()

创建一个新的对象,保存对象,并将它添加到关联对象集之中,返回新创建的对象。

>>> import datetime
>>> models.Author.objects.first().book_set.create(title="python入门",
    publish_date=datetime.date.today())

add()

把指定的model对象添加到关联对象集中。

添加对象

author_objs = models.Author.objects.filter(id__lt=3)
models.Book.objects.first().authors.add(*author_objs)

添加id

 models.Book.objects.first().authors.add(*[1, 2])

set()

更新model对象的关联对象。

book_obj = models.Book.objects.first()
book_obj.authors.set([2, 3])

remove()

从关联对象集中移除执行的model对象

book_obj = models.Book.objects.first()
book_obj.authors.remove(3)

clear()

从关联对象集中移除一切对象。

book_obj = models.Book.objects.first()
book_obj.authors.clear()

注意: 对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。

举个例子:

ForeignKey字段没设置null=True时,

class Book(models.Model):
    title = models.CharField(max_length=32)
    publisher = models.ForeignKey(to=Publisher)

没有clear()和remove()方法:

models.Publisher.objects.first().book_set.clear()
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'RelatedManager' object has no attribute 'clear' 

# 报错信息

当ForeignKey字段设置null=True时,

class Book(models.Model):
    name = models.CharField(max_length=32)
    publisher = models.ForeignKey(to=Class, null=True)

此时就有clear()和remove()方法:

models.Publisher.objects.first().book_set.clear()

注意:

        对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的 任何一端,都不需要再调用save()方法。

聚合查询和分组查询

聚合

        aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。 键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生 成出来的。

用到的内置函数:

from django.db.models import Avg, Sum, Max, Min, Count

示例:

from django.db.models import Avg, Sum, Max, Min, Count

 models.Book.objects.all().aggregate(Avg("price"))
 {'price__avg': 13.233333}

如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

 models.Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 13.233333}

如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道 所有图书价格的最大值和最小值,可以这样查询:

models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price"))
{'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}

分组

我们在这里先复习一下SQL语句的分组。 假设现在有一张公司职员表:

我们使用原生SQL语句,按照部门分组求平均工资:

select dept,AVG(salary) from employee group by dept;

ORM查询:

from django.db.models import Avg
Employee.objects.values("dept").annotate(avg=Avg("salary").values("dept", "avg")

SQL查询:

select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id)
group by dept_id;

ORM查询:

from django.db.models import Avg
models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")

 F查询和Q查询

        在ORM中,F查询和Q查询是两种常用的查询方法。

 F查询

        F查询是通过指定字段来进行查询,它允许我们只查询所需的字段,而不需要返回整个对象。例如,假设我们有一个User模型,它有name和age两个字段,我们可以使用F查询来查询年龄大于等于18的用户

      

from django.db.models import F

users = User.objects.filter(age__gte=F('age')+18)

  在这个例子中,age__gte=F('age')+18表示查询年龄大于等于age+18的用户。

  Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

Q查询

        Q查询是通过使用逻辑运算符来进行查询,它允许我们根据多个条件来组合查询。例如,假设我们有一个User模型,它有name和age两个字段,我们可以使用Q查询来查询名字包含"John"且年龄大于等于18的用户:

from django.db.models import Q

users = User.objects.filter(Q(name__contains='John') & Q(age__gte=18))

        在这个例子中,Q(name__contains='John')Q(age__gte=18)表示查询名字包含"John"且年龄大于等于18的用户。

        F查询和Q查询可以结合使用,以满足更复杂的查询需求。无论是F查询还是Q查询,都可以提高查询的灵活性和效率。

总结

        以上就是今天要讲的内容,本文仅仅简单介绍了ORM的使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值