Django ORM(Object-Relational Mapping)是Django框架中的一个重要组成部分,用于简化与数据库的交互。它提供了一种将数据库中的数据映射到Python对象的方法,使得开发者能够使用面向对象的方式来操作数据库,而无需直接使用SQL语句。Django ORM简化了数据库交互的复杂性,提高了开发效率,同时保持了良好的可维护性。通过使用ORM,开发者可以专注于业务逻辑而不用过多关注底层的数据库细节。
Django ORM 的主要作用包括:
Django ORM允许开发者定义Python类,这些类映射到数据库中的表,类的属性映射到表的字段。这种映射关系允许开发者通过操作Python对象来实现对数据库的操作,而不用直接处理SQL语句。
使用Django ORM,可以使用高级的查询API来执行数据库查询,而无需手写复杂的SQL语句。查询API提供了许多方法,例如 filter
、exclude
、annotate
等,用于构建灵活且强大的数据库查询。
Django ORM 提供了一层抽象,使得可以轻松切换底层的数据库引擎,而不用改变应用程序的代码。这种抽象提高了应用程序的灵活性和可维护性。
Django ORM 支持事务管理,确保数据库操作的原子性。开发者可以使用 atomic
装饰器或 with transaction.atomic()
上下文管理器来定义事务,以确保一系列数据库操作要么全部成功,要么全部回滚。
Django ORM 支持定义模型之间的关系,如一对多、多对一、多对多等。这些关系被映射到数据库的外键、中间表等结构,使得在应用程序中更容易表示和处理数据之间的关联。
Django 的 ORM 提供了多种查询方法,允许开发者执行灵活而强大的数据库查询。以下是一些常用的 Django ORM 查询方法:
**all()**
: 返回模型的所有对象。
all_objects = MyModel.objects.all()
**get(**kwargs)**
: 根据给定的条件获取单个对象。
my_object = MyModel.objects.get(name='example')
**filter(**kwargs)**
: 根据给定的条件过滤对象集。
filtered_objects = MyModel.objects.filter(name='example')
**exclude(**kwargs)**
: 排除满足给定条件的对象。
excluded_objects = MyModel.objects.exclude(name='example')
**order_by(*fields)**
: 按照指定字段对结果进行排序。
ordered_objects = MyModel.objects.order_by('name', '-created_at')
**values(*fields)**
: 返回包含指定字段的字典的 QuerySet。
values_list = MyModel.objects.values('name', 'created_at')
**count()**
: 返回满足条件的对象数量。
object_count = MyModel.objects.filter(name='example').count()
**exists()**
: 检查是否存在满足条件的对象。
has_objects = MyModel.objects.filter(name='example').exists()
**first()**
** 和 **last()**
:** 返回满足条件的第一个或最后一个对象。
first_object = MyModel.objects.filter(name='example').first()
last_object = MyModel.objects.filter(name='example').last()
链式查询: 可以链式组合多个查询方法,形成复杂的查询。
result = MyModel.objects.filter(name='example').exclude(status='inactive').order_by('-created_at')
**annotate()**
: 使用聚合函数对查询结果进行注释。
from django.db.models import Count
annotated_result = MyModel.objects.values('category').annotate(category_count=Count('category'))
**distinct()**
: 返回去重后的结果。
distinct_objects = MyModel.objects.values('name').distinct()
**values_list(*fields, flat=False)**
: 返回包含指定字段的元组的 QuerySet。
values_list = MyModel.objects.values_list('name', 'created_at', flat=True)
**update(**kwargs)**
: 更新满足条件的对象的字段值。
MyModel.objects.filter(name='old_name').update(name='new_name')
**delete()**
: 删除满足条件的对象。
MyModel.objects.filter(name='example').delete()
**raw(raw_query, params=None)**
: 允许执行原始 SQL 查询。
raw_query_result = MyModel.objects.raw('SELECT * FROM myapp_mymodel WHERE name = %s', ['example'])
**defer(*fields)**
** 和 **only(*fields)**
:** 控制选择性地延迟或仅选择加载的字段。
deferred_objects = MyModel.objects.defer('description')
only_selected_objects = MyModel.objects.only('name', 'created_at')
**select_related(*fields)**
** 和 **prefetch_related(*fields)**
:** 优化查询,减少关联对象的查询次数。
selected_related_objects = MyModel.objects.select_related('related_model')
prefetch_related_objects = MyModel.objects.prefetch_related('related_set')
**filter(Q())**
: 使用复杂的查询逻辑。
from django.db.models import Q
complex_query = MyModel.objects.filter(Q(name='example') | Q(name='another_example'))
**F()**
** 表达式:** 使用数据库字段值进行查询。
from django.db.models import F
increased_objects = MyModel.objects.filter(count__gt=F('threshold'))
**aggregate()**
: 使用聚合函数对查询结果进行汇总。
from django.db.models import Avg
average_count = MyModel.objects.aggregate(average=Avg('count'))
**extra()**
: 允许添加额外的 SQL 片段到查询中。
extra_query = MyModel.objects.extra(where=["name LIKE %s"], params=['example%'])
**in_bulk()**
: 通过指定的 ID 列表获取对象字典。
id_list = [1, 2, 3]
objects_dict = MyModel.objects.in_bulk(id_list)
**dates()**
** 和 **datetimes()**
:** 获取日期或日期时间字段的聚合结果。
from django.db.models import Count
date_aggregation = MyModel.objects.dates('created_at', 'month', order='DESC')
datetime_aggregation = MyModel.objects.datetimes('created_at', 'minute', order='DESC')
**values()**
** 和 **values_list()**
的聚合:** 对查询结果进行聚合操作。
from django.db.models import Count
aggregated_values = MyModel.objects.values('category').annotate(category_count=Count('category'))
aggregated_values_list = MyModel.objects.values_list('name').annotate(name_count=Count('name'))
**bulk_create()**
: 批量创建对象,减少数据库插入操作的次数。
objects_to_create = [MyModel(name='example1'), MyModel(name='example2')]
MyModel.objects.bulk_create(objects_to_create)
**reverse()**
: 反转查询集的顺序。
reversed_objects = MyModel.objects.all().reverse()
**first()**
** 和 **last()**
的默认值:** 为 first()
和 last()
指定默认值。
first_object_or_default = MyModel.objects.filter(name='nonexistent').first(default=None)
last_object_or_default = MyModel.objects.filter(name='nonexistent').last(default=None)
**get_or_create()**
: 尝试获取对象,如果不存在则创建。
obj, created = MyModel.objects.get_or_create(name='example', defaults={'description': 'example description'})
Django 的 ORM(对象关系映射)和 SQL 查询语言是用于与数据库交互的两种不同的方法,它们在语法和使用上有一些显著的区别:
Django ORM:
SQL 查询语言:
在 Django 中创建模型是定义数据库表结构的关键步骤之一。以下是创建一个简单模型的基本步骤:
models.py
文件,并创建一个继承自 django.db.models.Model
的类。每个类属性都代表表中的一个字段。# models.py
from django.db import models
class MyModel(models.Model):
# 定义模型的字段
name = models.CharField(max_length=100)
description = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
在这个例子中,MyModel
模型有三个字段:name
(CharField)、description
(TextField)和 created_at
(DateTimeField)。
python manage.py makemigrations
python manage.py migrate
这将根据模型类创建数据库表。
# views.py
from django.shortcuts import render
from .models import MyModel
def my_view(request):
# 获取所有 MyModel 对象
my_objects = MyModel.objects.all()
return render(request, 'my_template.html', {'my_objects': my_objects})
这是一个简单的例子,演示了如何在视图中查询所有 MyModel
对象。
admin.py
中注册模型。# admin.py
from django.contrib import admin
from .models import MyModel
admin.site.register(MyModel)
在Django的模型(Model)中,模型字段用于定义数据库表中的字段,每个字段对应表中的一个列。模型字段定义了该列的数据类型、验证规则和其他属性。以下是一些常见的Django模型字段类型的例子:
用于存储短文本字符串,例如名称、标题等。
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=100)
用于存储整数。
class Book(models.Model):
pages = models.IntegerField()
用于存储浮点数。
class Product(models.Model):
price = models.FloatField()
用于存储日期。
class Event(models.Model):
date = models.DateField()
用于存储日期和时间。
class Article(models.Model):
published_at = models.DateTimeField()
用于存储布尔值(True或False)。
class Task(models.Model):
completed = models.BooleanField(default=False)
用于存储电子邮件地址。
class Contact(models.Model):
email = models.EmailField()
用于存储图像文件路径。
class UserProfile(models.Model):
profile_picture = models.ImageField(upload_to='profile_pics/')
用于建立与另一个模型的关联。例如,一个模型可以包含指向另一个模型的外键,表示两个模型之间的关系。
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
用于表示多对多的关系,一个模型中的一个字段可以与多个目标模型建立关联。
class Student(models.Model):
courses = models.ManyToManyField(Course)
数据库迁移是指对 Django 项目中的数据库模型进行更改,并将这些更改应用到实际的数据库的过程。迁移允许你在应用程序的开发过程中修改数据库结构,而不会导致数据丢失或不一致。
在 Django 应用程序中的 models.py
文件中定义你的模型。这可以包括新的模型、字段的添加或修改等。
在终端中运行以下命令,生成一个新的数据库迁移文件。Django 将比较模型的变化并生成相应的SQL语句。
python manage.py makemigrations
可以查看生成的迁移文件,确认数据库迁移包含了你期望的变化。
python manage.py sqlmigrate your_app_name migration_number
运行以下命令,将迁移应用到数据库中,实际修改数据库结构。
python manage.py migrate
如果你的模型包含了用户或权限相关的更改,可能需要创建超级用户。
python manage.py createsuperuser
可以运行以下命令,查看当前数据库的状态,确保所有迁移都已应用。
python manage.py showmigrations
在 Django 模型中,CharField
和 TextField
是两种用于存储文本数据的字段类型,它们之间的主要区别在于存储的文本数据的长度和用途。
CharField:
max_length
参数。class Product(models.Model):
name = models.CharField(max_length=255)
TextField:
class Article(models.Model):
content = models.TextField()
CharField
用于存储有限长度的文本数据,而 TextField
则用于存储不受限制的文本数据。在选择使用哪种类型时,可以根据数据的特性和存储需求来决定。如果你知道文本数据的最大长度,并且长度不会太长,那么使用 CharField
是合适的。如果文本数据可能会很长或长度不确定,那么使用 TextField
更合适。
在 Django 模型中,你可以使用 ForeignKey
和 ManyToManyField
字段来定义外键关系和多对多关系。
外键关系(ForeignKey):
外键用于建立模型之间的一对多关系,其中一个模型的一个实例对应另一个模型的多个实例。
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
在上面的例子中,Book
模型包含一个 ForeignKey
字段,该字段建立了与 Author
模型的外键关系。on_delete=models.CASCADE
表示当关联的作者记录被删除时,与之关联的书籍记录也会被删除。
多对多关系(ManyToManyField):
多对多关系用于建立模型之间的多对多关系,其中一个模型的一个实例可以与另一个模型的多个实例关联。
from django.db import models
class Student(models.Model):
name = models.CharField(max_length=100)
class Course(models.Model):
title = models.CharField(max_length=200)
students = models.ManyToManyField(Student)
在上面的例子中,Course
模型包含一个 ManyToManyField
字段,该字段建立了与 Student
模型的多对多关系。每个课程可以有多个学生,每个学生可以选修多个课程。
需要注意的是,在使用 ManyToManyField
时,Django 会自动创建一个中间表来维护关联关系。
在 Django 中,模型管理器(Model Manager)是一个负责查询数据库的工具,它允许你执行数据库查询和与模型相关的其他数据库操作。每个 Django 模型都有一个默认的模型管理器,但你也可以自定义模型管理器以添加自定义的查询方法或其他功能。
默认模型管理器:
每个 Django 模型都有一个默认的模型管理器,可以通过 objects
属性访问。例如:
class MyModel(models.Model):
name = models.CharField(max_length=100)
# 使用默认模型管理器
instances = MyModel.objects.all()
自定义模型管理器:
你可以创建自定义的模型管理器,以添加自定义的查询方法或其他功能。通常,自定义管理器是通过继承 models.Manager
类来实现的。
from django.db import models
class MyModelManager(models.Manager):
def custom_query(self):
# 自定义查询逻辑
return self.filter(...) # 例如,使用 filter 进行过滤操作
class MyModel(models.Model):
name = models.CharField(max_length=100)
# 使用自定义模型管理器
custom_objects = MyModelManager()
在上面的例子中,MyModelManager
继承自 models.Manager
类,然后在 MyModel
模型中通过 custom_objects
属性引入了这个自定义管理器。现在,你可以使用 custom_objects
执行自定义的查询操作:
# 使用自定义模型管理器执行查询
custom_instances = MyModel.custom_objects.custom_query()
默认管理器的替换:
如果你想替换模型的默认管理器,可以在模型中使用 objects
属性定义一个新的管理器。这样,你就可以使用新的管理器名称来执行查询。
from django.db import models
class MyCustomModelManager(models.Manager):
def custom_query(self):
return self.filter(...)
class MyModel(models.Model):
name = models.CharField(max_length=100)
# 替换默认模型管理器
objects = MyCustomModelManager()
在上面的例子中,objects
属性被重新定义为 MyCustomModelManager
,这样 MyModel
将使用这个新的管理器作为默认管理器。自定义模型管理器为你提供了在模型层面组织和扩展查询逻辑的能力,使得你能够更方便地封装数据库操作和提供更清晰的 API。
Django 支持多种数据库后端,允许你选择适合你应用需求的数据库引擎。以下是一些常见的数据库后端:
切换数据库后端:
**DATABASES**
设置:在项目的 settings.py
文件中,你可以找到 DATABASES
设置,这是一个字典,用于配置数据库连接。修改 ENGINE
键的值来切换数据库后端。以下是一些常见的示例:
# 使用 SQLite(默认设置)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / "db.sqlite3",
}
}
# 使用 PostgreSQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
# 使用 MySQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '3306',
}
}
数据库索引是一种优化数据库查询性能的机制,它提供了一种快速访问数据的方式。索引是数据库表上一个或多个列的数据结构,它们被组织为树形结构,以加速对表中数据的检索。在 Django 中,你可以使用模型的 indexes
属性来定义数据库索引。
创建索引:
在模型的 Meta
类中,使用 indexes
属性定义索引。以下是一个示例:
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
class Meta:
indexes = [
models.Index(fields=['name'], name='name_idx'),
models.Index(fields=['name', 'age'], name='name_age_idx'),
]
在上面的例子中,定义了两个索引。name_idx
是对单个字段 name
的索引,name_age_idx
是对多个字段 name
和 age
的联合索引。
使用 **unique**
属性创建唯一索引:
如果你想要创建唯一索引,可以使用模型字段的 unique
属性,或者使用 unique_together
属性定义多字段的唯一性:
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100, unique=True)
age = models.IntegerField()
class Meta:
unique_together = [('name', 'age')]
在上面的例子中,name
字段上的 unique=True
属性创建了一个唯一索引,而 unique_together
定义了对多个字段的唯一性要求。
迁移:
创建或修改索引后,你需要运行 Django 数据库迁移以应用这些更改:
python manage.py makemigrations
python manage.py migrate
Django 将生成相应的数据库命令来创建或修改索引。注意:在大型数据库中使用索引可能会提高读取性能,但也会增加写入操作的开销。因此,在设计索引时需要权衡查询性能和写入性能。
在 Django 模型中,抽象基类(Abstract Base Classes)是一种用于封装共享字段和方法的方式,但不会创建数据库表。它为模型提供了一种代码重用的机制,让你能够定义一组字段和方法,并在其他模型中继承它们。
要创建一个抽象基类,你需要使用 abstract
属性将其设置为 True
。以下是一个简单的例子:
from django.db import models
class BaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class MyModel(BaseModel):
name = models.CharField(max_length=100)
description = models.TextField()
在上面的例子中,BaseModel
是一个抽象基类,包含了 created_at
和 updated_at
两个字段。MyModel
继承了 BaseModel
,因此它会继承这两个字段,但并不会创建 BaseModel
对应的数据库表。
其他模型可以通过继承抽象基类来使用其中定义的字段和方法:
class AnotherModel(BaseModel):
title = models.CharField(max_length=200)
content = models.TextField()
在上面的例子中,AnotherModel
继承了 BaseModel
,因此它也拥有 created_at
和 updated_at
两个字段,同时不会创建 BaseModel
对应的数据库表。
on_delete
参数,以定义在抽象基类被删除时的行为。