Django 的 `Meta` 类和外键的使用

Django 的 `Meta` 类和外键的使用

      • [1. `Meta` 类的常用选项](#1. Meta 类的常用选项)
      • [2. 外键(ForeignKey)字段的使用](#2. 外键(ForeignKey)字段的使用)
        • [2.1 基本用法](#2.1 基本用法)
        • [2.2 `ForeignKey` 参数](#2.2 ForeignKey 参数)
        • [2.3 外键删除选项(`on_delete`)](#2.3 外键删除选项(on_delete))
      • [3. 外键和查询](#3. 外键和查询)
        • [3.1 获取作者的所有书籍](#3.1 获取作者的所有书籍)
        • [3.2 通过书籍查找作者](#3.2 通过书籍查找作者)
        • [3.3 使用 `select_related` 优化查询](#3.3 使用 select_related 优化查询)
      • 总结

在 Django 中,Meta 类是模型的一个内部类,用来配置模型的行为和一些数据库选项。通过在模型中定义 Meta 类,你可以控制模型的一些特性,如数据库表名、排序方式、索引、唯一约束等。

1. Meta 类的常用选项

以下是 Meta 类中常用的配置选项:

  • db_table:指定数据库表的名称。如果没有指定,Django 会默认使用模型类名的小写形式作为表名。

    python 复制代码
    class Tank(models.Model):
        name = models.CharField(max_length=100)
        speed = models.FloatField()
    
        class Meta:
            db_table = 'tank_table'  # 指定数据库表名
  • ordering:指定模型数据的默认排序方式。它接受一个字段名的列表(可以带负号表示降序)。

    python 复制代码
    class Tank(models.Model):
        name = models.CharField(max_length=100)
        speed = models.FloatField()
    
        class Meta:
            ordering = ['-speed']  # 按照速度降序排列
  • verbose_nameverbose_name_plural:用于指定模型的单数和复数形式的可读名称,通常用于 Django 管理后台显示模型名称。

    python 复制代码
    class Tank(models.Model):
        name = models.CharField(max_length=100)
        speed = models.FloatField()
    
        class Meta:
            verbose_name = 'Tank'
            verbose_name_plural = 'Tanks'
  • unique_together:指定多个字段组合成的联合唯一约束。Django 会确保这组字段的组合在数据库中是唯一的。

    python 复制代码
    class Tank(models.Model):
        name = models.CharField(max_length=100)
        speed = models.FloatField()
    
        class Meta:
            unique_together = ['name', 'speed']  # 确保每个name和speed组合是唯一的
  • index_together:为多个字段组合创建数据库索引,提高查询效率。

    python 复制代码
    class Tank(models.Model):
        name = models.CharField(max_length=100)
        speed = models.FloatField()
    
        class Meta:
            index_together = ['name', 'speed']  # 为name和speed创建联合索引
  • permissions :指定模型的权限。这会在 auth_permission 表中创建自定义权限。

    python 复制代码
    class Tank(models.Model):
        name = models.CharField(max_length=100)
        speed = models.FloatField()
    
        class Meta:
            permissions = [
                ("can_drive", "Can drive the tank"),
                ("can_fight", "Can fight with the tank")
            ]
  • default_manager_name :设置默认的管理器名称,Django 会在模型类中自动创建 objects 管理器。如果你有多个管理器,可以通过这个选项指定默认的一个。

    python 复制代码
    class Tank(models.Model):
        name = models.CharField(max_length=100)
        speed = models.FloatField()
    
        active_tanks = models.Manager()  # 自定义管理器
    
        class Meta:
            default_manager_name = 'active_tanks'  # 使用自定义的管理器

2. 外键(ForeignKey)字段的使用

Django 的 ForeignKey 字段用于表示模型之间的"一对多"关系。在外键关系中,一个对象可以关联多个对象,常用于表示父子表关系。

2.1 基本用法

ForeignKey 用于表示两个模型之间的外键关系。通常情况下,它会生成一个新的字段,在数据库中存储关联对象的主键(id)。

假设我们有两个模型:AuthorBook。每本书都由一个作者编写,因此我们需要在 Book 模型中添加一个外键字段,指向 Author 模型。

python 复制代码
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name


class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)  # 外键关系,关联到 Author 模型

    def __str__(self):
        return self.title
2.2 ForeignKey 参数
  • to :指定外键关联的模型类。可以是另一个模型的类名或字符串(例如 'Author')。
  • on_delete :当关联对象(如作者)被删除时,当前对象(如书籍)该如何处理。常见的选项包括:
    • models.CASCADE:级联删除,删除父对象时删除所有关联的子对象。
    • models.PROTECT:阻止删除父对象,如果该对象仍被引用。
    • models.SET_NULL:将外键字段设置为 NULL(前提是该字段允许为 NULL)。
    • models.SET_DEFAULT:将外键字段设置为默认值。
    • models.SET():可以设置一个特定的值。
  • related_name :为反向关系定义名称。即通过外键模型,可以反向查询到当前模型实例的集合。默认情况下,Django 会使用模型名的小写形式加上 _set 作为反向查询的名称。
  • related_query_name:用于在查询时指定反向关系的名称。
  • null :如果为 True,外键可以为空。
  • blank :如果为 True,字段可以在表单中为空。

例如,添加 related_name 来进行反向查询:

python 复制代码
class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name


class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')  # 定义反向查询名称

    def __str__(self):
        return self.title

现在,如果你有一个 author 实例,你可以通过 author.books.all() 获取该作者所有的书籍:

python 复制代码
author = Author.objects.get(id=1)
books_by_author = author.books.all()  # 获取该作者所有的书籍
2.3 外键删除选项(on_delete

当父对象被删除时,Django 会根据你设置的 on_delete 参数来处理外键关系。以下是常用的 on_delete 选项:

  • models.CASCADE:删除父对象时,删除所有引用该父对象的子对象。

    python 复制代码
    author = Author.objects.get(id=1)
    author.delete()  # 删除作者时,所有关联的书籍也会被删除
  • models.PROTECT:如果该父对象仍被引用,禁止删除父对象。

    python 复制代码
    author = Author.objects.get(id=1)
    author.delete()  # 如果有书籍关联,删除时会引发异常
  • models.SET_NULL :将外键字段设置为 NULL。需要确保外键字段允许 NULL

    python 复制代码
    class Book(models.Model):
        title = models.CharField(max_length=200)
        author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True)
  • models.SET_DEFAULT:将外键字段设置为默认值。

    python 复制代码
    class Book(models.Model):
        title = models.CharField(max_length=200)
        author = models.ForeignKey(Author, on_delete=models.SET_DEFAULT, default=1)
  • models.SET():你可以指定一个函数或值,当父对象删除时,外键字段会设置为指定的值。

    python 复制代码
    class Book(models.Model):
        title = models.CharField(max_length=200)
        author = models.ForeignKey(Author, on_delete=models.SET('Unknown Author'))

3. 外键和查询

在 Django 中,你可以轻松地使用外键字段进行查询。例如:

3.1 获取作者的所有书籍
python 复制代码
author = Author.objects.get(id=1)
books = author.books.all()  # 获取该作者的所有书籍
3.2 通过书籍查找作者
python 复制代码
book = Book.objects.get(id=1)
author = book.author  # 获取书籍的作者

如果你查询外键字段时,经常会发起额外的数据库查询。你可以使用 select_related 来一次性加载相关的外键数据,减少查询次数。

python 复制代码
books = Book.objects.select_related('author').all()  # 一次性查询所有书籍及其对应的作者

总结

  • Meta 类用于在模型中配置数据库表的选项,如表名、排序、索引等。
  • 外键字段(ForeignKey)用于表示模型之间的"一对多
相关推荐
CC呢10 分钟前
基于STM32单片机火灾安全监测一氧化碳火灾
数据库·mongodb
Channing Lewis27 分钟前
flask实现重启后需要重新输入用户名而避免浏览器使用之前已经记录的用户名
后端·python·flask
Channing Lewis29 分钟前
如何在 Flask 中实现用户认证?
后端·python·flask
MasterNeverDown39 分钟前
解决 PostgreSQL 中创建 TimescaleDB 扩展的字符串错误
数据库·postgresql·oracle
水银嘻嘻41 分钟前
【Mac】Python相关知识经验
开发语言·python·macos
汤姆和佩琦1 小时前
2025-1-20-sklearn学习(42) 使用scikit-learn计算 钿车罗帕,相逢处,自有暗尘随马。
人工智能·python·学习·机器学习·scikit-learn·sklearn
我的运维人生1 小时前
Java并发编程深度解析:从理论到实践
java·开发语言·python·运维开发·技术共享
limts1 小时前
Oracle之开窗函数使用
数据库·oracle
lljss20202 小时前
python创建一个httpServer网页上传文件到httpServer
开发语言·python
Makesths2 小时前
【python基础】用Python写一个2048小游戏
python