Django中ForeignKey参数的使用

本文介绍Django中如何使用limit_choices_to限制外键字段的可选范围,以及related_name参数的使用方法,帮助理解模型间的关系及查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

limit_choices_to:

from django.db import models
from django.contrib.auth.models import User
from django.db.models import Q


class Book(models.Model):
name = models.CharField(max_length=20)
user = models.ForeignKey(User, limit_choices_to={'is_staff': True})
#user = models.ForeignKey(User, limit_choices_to=Q(is_staff=True))
    def __unicode__(self):
        return self.name

>>>Book.objects.filter(user=u)

>>>User.objects.filter(Book__name__startswith='hhh')


limit_choices_to可以使用字典的形式来表示,也可以用Q来表示,如上实例所示。

但是当使用Q的形式来表示时,那么用到limit_choices_to的字段就不要出现在raw_id_fields中,否则将会失效。而字典的形式照常生效。

class BookAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'user']
raw_id_fields = ('user',)
admin.site.register(Book, BookAdmin)

这样的话,limit_choices_to的作用就会失效。

related_name:

当一张表的多个字段指向同一张表时,会出错。系统无法知道,通过另外一张表,访问XXX_set属性访问到的是哪个属性。这时,我们就需要为每个字段定义一个related_name属性,另外一张表访问这个表时,就会根据related_name的值来得到各个属性了。

例子:

[python]  view plain copy
  1. class dutyTeam(models.Model):  
  2.     ''''' 
  3.     这里必须定义related_name属性。 
  4.     '''  
  5.     first=models.ForeignKey(watch,verbose_name='第一值班人',related_name='first')  
  6.     second=models.ForeignKey(watch,related_name='second',verbose_name='备用值班人')  
  7.     urgent=models.ForeignKey(watch,related_name='urgent',verbose_name='紧急联系人')  

当定义了related_name后”_set”这类查询就被related_name代替了,所以用”_set”会报错。

如果related_name=‘+’或者以‘+’结束:‘user+',那么就无法实现逆向查询了。

参数描述
edit_inline若取值非假, 这个关联对象就是可内联编辑的.这也意味着这个对象没有自己的管理界面.取值可以是 models.TABULAR 或 models.STACKED, 分别表示内联可编辑对象是显示成表格形式还是一个字段集栈的形式.
limit_choices_to

一个参数和值的字典(参阅`数据库API参考`_)用来限制 admin 针对该对象的可选项. 使用models.LazyDate 值来按日期限制该对象的选择项,举例来说:

limit_choices_to = {'pub_date__lte' : models.LazyDate()}

只允许关联对象的pub_date在当前日期之前的才可以被选择.

本参数与 edit_inline 不相容.

max_num_in_admin

对内联编辑对象来说,这是在 amdin 中可显示的关联对象的最大值. 这样, 如果说一只比萨饼最多加10种浇头,那么 max_num_in_admin=10 将确保没有一个超过十种.

这并不说是比萨斜塔只有十层高...比萨斜塔是可以有更多层的.这个参数仅仅控制admin界面.

min_num_in_admin在admin中显示的关联对象的最小值. 正常情况,在创建阶段显示 num_in_admin 个内联对象, 在编辑阶段,除了预先存在的关联对象外, 显示 num_extra_on_change 个空对象.不过, 无论何种情况,至少会有 min_num_in_admin 个关联对象被显示出来.
num_extra_on_change在编辑阶段显示的额外的空白关联对象字段数.
num_in_admin在添加一个对象时显示的其内联对象的默认数量
raw_id_admin

为即将得到的整数值(id值)显示一个文本框而不是一个下拉菜单. 在关联对象有很多很多行时.使用它就比使用一个 <select> 更实用.

不能与 edit_inline 一起使用.

related_name

关系名字. 举例来说, 如果 Topping 对象拥有字段:

models.ForeignKey(Pizza)

related_name 将会是 "topping_set" (取自  的名字), Pizza 对象会自动拥有 topping_set对象集描述符.

不过若你在 Topping 类中做如下定义的话:

models.ForeignKey(Pizza, related_name="munchie")

则 Topping 的对象集描述符就变为 munchie.

只有当一个对象要被另一个对象关联不止一次时, 这个参数才真正有用. 举例来说, 如果一个Story 对象既有 primary_category 字段又有 secondary_category 字段. 为了确保Category 对象拥有正确的对象集描述符,你要这样使用这些字段.:

models.ForeignKey(Category, related_name="primary_storys")
models.ForeignKey(Category, related_name="secondary_storys")

...这样 Category 对象才会自动拥有 primary_storys 和 secondary_storys 对象集描述符.

to_field被关联对象的用于关联的字段. 默认情况, Django 使用被关联对象的主键


### Django 中 `ForeignKey` 函数的使用说明 #### 一、`ForeignKey` 的基本概念 `ForeignKey` 是 Django ORM 提供的一种字段类型,用于表示两个模型之间的一对多关系。这种关系意味着一个父级记录可以拥有多个子级记录,而每个子级记录只属于一个父级记录[^3]。 例如,在书籍管理系统中,一本书可能只有一个作者,但一位作者可能会写多本书。因此,`Book` 模型可以通过 `ForeignKey` 关联到 `Author` 模型。 --- #### 二、`ForeignKey` 的标准语法 以下是 `ForeignKey` 字段的基本定义方式: ```python class ModelName(models.Model): field_name = models.ForeignKey( RelatedModel, on_delete=models.CASCADE, related_name='optional_reverse_relation', null=False, blank=False, db_column='optional_db_column' ) ``` - **RelatedModel**: 表示与当前模型建立外键关系的目标模型。 - **on_delete**: 当关联的对象被删除时的行为选项。常见值包括: - `models.CASCADE`: 删除关联对象时也删除依赖该对象的其他对象。 - `models.PROTECT`: 防止删除关联对象。 - `models.SET_NULL`: 将外键字段设为 NULL(前提是允许 NULL)。 - `models.SET_DEFAULT`: 设置默认值。 - `models.DO_NOTHING`: 不采取任何行动。 - **related_name**: (可选)指定从目标模型反向查询当前模型的关系名称。 - **null**: (布尔值,默认 False)是否允许数据库层面存储 NULL 值。 - **blank**: (布尔值,默认 False)是否允许表单验证时为空。 - **db_column**: (可选)自定义数据库中外键列的名字。 --- #### 三、实际案例分析 ##### 1. 定义模型并创建外键关系 以下是一个简单的例子,展示如何在 `Book` 和 `Author` 模型间建立外键关系[^3]: ```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=100) author = models.ForeignKey(Author, on_delete=models.CASCADE) def __str__(self): return f"{self.title} by {self.author}" ``` 在这个例子中,每本 `Book` 都有一个唯一的 `author`,而每位 `Author` 可能有多本书籍。 --- ##### 2. 数据库操作演示 利用上述模型,我们可以通过以下代码进行数据交互: ###### 创建和保存对象 ```python # 创建一个新的作者 author = Author(name="J.K. Rowling") author.save() # 创建一本新书,并将其绑定到特定作者 book = Book(title="Harry Potter and the Sorcerer's Stone", author=author) book.save() ``` ###### 查询相关数据 通过外键关系,可以从任意一侧轻松访问另一侧的数据[^4]: - 获取某位作者的所有书籍: ```python books_by_author = author.book_set.all() # 使用 default reverse relation 名称 for book in books_by_author: print(book.title) ``` - 或者显式指定 `related_name` 后更直观地访问: ```python class Book(models.Model): title = models.CharField(max_length=100) author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books') # 访问更加语义化的方式 books_by_author = author.books.all() ``` --- ##### 3. 性能优化技巧 在外键场景下,频繁触发 N+1 查询可能导致性能瓶颈。为此,Django 提供了两种主要机制来解决这一问题:`select_related` 和 `prefetch_related`[^1]。 - **`select_related`**: 适用于单一或嵌套外键链路的情况,能够提前加载所需的相关数据。 ```python authors_with_books = Author.objects.select_related('book').all() for author in authors_with_books: print(author.book.title) # 已经预取,不会再次发起 SQL 查询 ``` - **`prefetch_related`**: 适合处理多对多或多对外键集合的情形,批量获取所有关联项。 ```python authors_with_all_books = Author.objects.prefetch_related('book_set').all() for author in authors_with_all_books: for book in author.book_set.all(): print(book.title) # 批量预取,减少重复查询次数 ``` --- #### 四、注意事项 - 正确设置 `on_delete` 参数非常重要,因为它决定了当父级对象被移除时会发生什么行为。 - 如果需要双向导航能力,请考虑添加合适的 `related_name` 属性以增强代码可读性和逻辑清晰度。 - 在大规模生产环境中务必关注潜在的性能隐患,适时运用 `select_related` 或 `prefetch_related` 方法降低开销。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值