Django模型字段详解与ORM查询操作指南

栗子
栗子
发布时间:2026-10-14| 4人浏览过
原创

本文系统梳理Django中Model的常用字段类型,涵盖字符、整数、日期及关系型字段。通过书籍、作者与出版社的示例,演示一对多与多对多关系的定义。详细解析对象获取、筛选、排序、连表查询及批量更新删除等核心操作,并介绍自定义Manager与原生SQL执行的高级用法。

Django模型常用字段类型概览

在Django中定义模型时,选择合适的字段类型至关重要。常用的字段包括用于存储字符串的CharField和TextField,用于存储整数的IntegerField,以及用于处理日期时间的DateField和DateTimeField。此外,还有专门用于存储邮箱、URL、图片、文件路径等特定数据的字段类型,开发者需根据实际业务需求进行选择。


V=models.CharField(max_length=None[, **options])    #varchar
V=models.EmailField([max_length=75, **options])    #varchar
V=models.URLField([verify_exists=True, max_length=200, **options])    #varchar
V=models.FileField(upload_to=None[, max_length=100, **options])    #varchar
#upload_to指定保存目录可带格式,
V=models.ImageField(upload_to=None[, height_field=None, width_field=None, max_length=100, **options])
V=models.IPAddressField([**options])    #varchar
V=models.FilePathField(path=None[, match=None, recursive=False, max_length=100, **options]) #varchar
V=models.SlugField([max_length=50, **options])    #varchar,标签,内含索引
V=models.CommaSeparatedIntegerField(max_length=None[, **options])    #varchar
V=models.IntegerField([**options])    #int
V=models.PositiveIntegerField([**options])    #int 正整数
V=models.SmallIntegerField([**options])    #smallint
V=models.PositiveSmallIntegerField([**options])    #smallint 正整数
V=models.AutoField(**options)    #int;在Django代码内是自增
V=models.DecimalField(max_digits=None, decimal_places=None[, **options])    #decimal
V=models.FloatField([**options])    #real
V=models.BooleanField(**options)    #boolean或bit
V=models.NullBooleanField([**options])    #bit字段上可以设置上null值
V=models.DateField([auto_now=False, auto_now_add=False, **options])    #date
#auto_now最后修改记录的日期;auto_now_add添加记录的日期
V=models.DateTimeField([auto_now=False, auto_now_add=False, **options])    #datetime
V=models.TimeField([auto_now=False, auto_now_add=False, **options])    #time
V=models.TextField([**options])    #text
V=models.XMLField(schema_path=None[, **options])    #text
——————————————————————————–
V=models.ForeignKey(othermodel[, **options])    #外键,关联其它模型,创建关联索引
V=models.ManyToManyField(othermodel[, **options])    #多对多,关联其它模型,创建关联表
V=models.OneToOneField(othermodel[, parent_link=False, **options])    #一对一,字段关联表属性

为了直观展示模型之间的关系,我们构建了一个简化的示例场景,涉及书籍、作者和出版社三个核心实体。在这个模型设计中,书籍表通过外键(ForeignKey)与出版社表建立一对多关联,即一本书归属于一个特定的出版社。同时,书籍与作者之间通过多对多关系(ManyToManyField)进行关联,允许一本书拥有多位作者,而一位作者也可以撰写多本书。

具体模型定义如下:出版社表包含名称字段;作者表包含名称和年龄字段;书籍表则包含书名、指向出版社的外键以及指向作者的多对多字段。这种结构清晰地反映了现实世界中出版关系的逻辑,便于后续进行数据存取操作。

书籍、作者与出版社关系模型示例


from django.db import models
class Publisher(models.Model):
  name = models.CharField(max_length=30)
 
  def __str__(self):
    return self.name
 
class Author(models.Model):
  name = models.CharField(max_length=30)
  age = models.IntegerField()
 
  def __str__(self):
    return self.name
 
class Book(models.Model):
  title = models.CharField(max_length=100)
  authors = models.ManyToManyField(Author)
  publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE)
 
  def __str__(self):
    return self.title

数据库对象获取与查询方法

在获取数据库对象时,Django提供了多种查询集(QuerySet)方法。开发者可以根据需要获取所有记录、筛选特定条件的记录、提取单个对象、对结果进行排序,或者执行连表查询和批量更新删除等操作。掌握这些基础查询方法是高效使用Django ORM的关键。

若需获取数据库中某一模型的所有记录,可以使用.all()方法。例如,通过Publisher.objects.all()可以返回包含所有出版社信息的查询集对象,该对象支持迭代和链式调用,是进行后续数据处理的基础。


Publisher.objects.all() #获取所有对象

当需要筛选符合特定条件的对象时,应使用.filter()方法。该方法返回一个包含所有匹配对象的查询集列表。例如,可以通过传递字典参数的方式动态构建过滤条件,如Author.objects.filter(**dict),这种方式在参数不确定时尤为灵活。


Publisher.objects.filter(name='人们教育出版社') #获取的是一个对象列表
dict = {'name':'lemon','age':18}
Author.objects.filter(**dict) #列表传参的方法

如果确定数据库中只存在一个匹配的对象,可以使用.get()方法直接获取该实例。需要注意的是,如果查询结果不存在或存在多个结果,.get()方法会抛出异常,因此在不确定结果数量时,建议使用.filter()配合索引或.first()方法。


Publisher.objects.get(name='机械工业出版社') #找不到会报错!!!

对查询结果进行排序可以使用.order_by()方法。该方法接受字段名作为参数,若字段名前加上负号(如-age),则表示按该字段降序排列。支持多字段排序,例如Author.objects.order_by("name","-age"),先按名称升序,名称相同时按年龄降序排列。


Author.objects.order_by("name","-age") #可以按照多个字段排序,- 表示逆向排序

连表查询通常涉及外键或多对多关系的访问。例如,通过Book.objects.filter(name='lemon').order_by('-age')[0]可以获取特定条件下的第一条记录。这种链式调用方式使得复杂查询变得简洁易读,开发者可以灵活组合各种查询条件。


Author.objects.filter(name='lemon').order_by('-age')[0]

批量更新操作可以使用.update()方法直接对查询集进行修改,并返回受影响的行数。例如,Author.objects.all().update(age='18')会将所有作者的年龄更新为18。这种方式比逐个获取对象再保存要高效得多,适用于大规模数据调整。


Author.objects.all().update(age='18')

删除对象可以使用.delete()方法。例如,Author.objects.filter(name='lemon').delete()会删除所有名称为'lemon'的作者记录。执行删除操作前需谨慎,建议先通过查询确认待删除的数据范围,避免误删重要数据。


Author.objects.filter(name='lemon').delete()

外键与多对多关系操作

处理外键和多对多关系时,Django提供了便捷的访问接口。通过外键字段可以直接访问关联对象,而多对多字段则返回一个关联对象的查询集。理解这些关系字段的访问方式,有助于简化复杂的数据库交互逻辑。

访问外键时,可以直接通过对象的外键属性获取关联对象。例如,Book.objects.get(id=1).publisher会返回该书对应的出版社对象。这种直接访问方式避免了手动编写JOIN语句,提高了代码的可读性和维护性。


Book.objects.get(id=1).publisher #得到书籍的出版社

反向查询允许从关联模型访问主模型。例如,通过models.Publisher.objects.get(id=1).book_set.all()可以获取该出版社出版的所有书籍。book_set是Django自动生成的反向关系管理器,返回的是一个包含所有关联书籍的查询集列表。


models.Publisher.objects.get(id=1).book_set.all() #反向查询,得到的是一个queryset对象列表

对于多对多关系,可以通过关联对象的.all()方法获取所有关联实例。例如,Book.objects.get(id=1).authors.all()会返回该书所有作者的列表。这种方式清晰地表达了多对多关系的语义,便于进行后续的增删改查操作。


Book.objects.get(id=1).authors.all() #得到queryset对象列表

自定义模型方法与Manager扩展

除了字段定义,Django模型还支持自定义方法。开发者可以在模型类中定义普通方法或属性,以封装特定的业务逻辑。例如,在Author模型中定义status()方法,根据作者名称返回特定的状态描述,如判断是否为特定用户并返回相应标签。


class Author(models.Model):
  name = models.CharField(max_length=30)
  age = models.IntegerField()

  def __str__(self):
    return self.name
  def status(self):
    if self.name=='lemon':
      return '帅哥'

以下代码演示了自定义模型方法的调用过程。通过Author.objects.get(id=1)获取特定作者对象,随后调用其status()方法,最终打印出该方法返回的状态信息。

aa = models.Author.objects.get(id=1) print(aa.status()) ———————————————运行结果—————————————————— 帅哥

Django允许自定义Manager管理器,以扩展默认的数据库查询功能。通过继承models.Manager类并重写或添加新方法,可以实现特定的数据聚合、统计或复杂查询逻辑。自定义Manager需要显式声明为模型的objects属性,以便在查询时使用。


class AuthorManager(models.Manager):
  def name_count(self,str_name):
    return self.filter(name__icontains=str_name).count()
class Author(models.Model):
  name = models.CharField(max_length=30)
  age = models.IntegerField()

  def __str__(self):
    return self.name
  def status(self):
    if self.name=='lemon':
      return '帅哥'
  #一旦定义了新的管理器,默认管理器需要显示声明出来才可以使用
  objects = models.Manger() #默认管理器
  object=AuthorManager() #新定义管理器

以下示例展示了如何定义并调用自定义Manager中的方法。通过Author.object.name_count('lemon'),可以获取名称中包含'lemon'的作者数量,结果直接返回整数计数值。

aa = models.Author.object.name_count('lemon') print(aa) #——————》2

在某些复杂场景下,可能需要执行原生SQL语句。Django提供了通过Manager执行原生SQL的方法,使用connection.cursor()创建游标,并执行SELECT语句。结果通过fetchall()获取,通常返回元组列表,开发者需自行解析数据结构。


class AuthorManager(models.Manager):
  def age_stat(self, age_int):
    cursor = connection.cursor()
    cursor.execute("""
      SELECT NAME
      FROM app2_author
      WHERE age = %s""", [age_int])
    #fetchall()返回的是元组的列表
    return [row[0] for row in cursor.fetchall()]
    
class Author(models.Model):
  name = models.CharField(max_length=30)
  age = models.IntegerField()
  # objects =models.Manager()
  object=AuthorManager()
  def __str__(self):
    return self.name

以下代码演示了如何执行原生SQL查询。通过AuthorManager中的age_stat方法,传入年龄参数,执行SELECT NAME FROM app2_author WHERE age = %s语句,并返回匹配的作者名称列表。

aa = models.Author.object.age_stat(18) print(aa) ----------------- ['lemon', 'Luouo']

字段过滤查找技巧总结

Django ORM提供了丰富的字段过滤查找方式,支持精确匹配、模糊查询、范围判断等多种条件。开发者可以根据需求选择合适的查找后缀,如exact用于精确匹配,contains用于包含子串,range用于范围查询,isnull用于空值判断等。

__exact 精确等于 like 'aaa' __iexact 精确等于 忽略大小写 ilike 'aaa' __contains 包含 like '%aaa%' __icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。 __gt 大于 __gte 大于等于 __lt 小于 __lte 小于等于 __in 存在于一个list范围内 __startswith 以...开头 __istartswith 以...开头 忽略大小写 __endswith 以...结尾 __iendswith 以...结尾,忽略大小写 __range 在...范围内 __year 日期字段的年份 __month 日期字段的月份 __day 日期字段的日 __isnull=True/False

以上涵盖了Django模型定义与ORM查询的核心操作。通过合理运用字段类型、关系定义及丰富的查询方法,可以高效地完成数据库交互任务。建议在实际开发中结合具体业务场景,灵活运用这些功能,以提升应用的性能与可维护性。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。