为模型中的外键字段设置默认值的最佳方法是什么?假设我有两个模型,Student
和Exam
,student使用exam_taken
作为外键。我该如何为它设置一个理想的默认值呢?这是我努力的记录
class Student(models.Model):
....
.....
exam_taken = models.ForeignKey("Exam", default=1)
可行,但我有预感还有更好的办法。
def get_exam():
return Exam.objects.get(id=1)
class Student(models.Model):
....
.....
exam_taken = models.ForeignKey("Exam", default=get_exam)
但这会失败,同步时出现表不存在错误。
任何帮助将不胜感激。
9条答案
按热度按时间h9a6wy2h1#
我会稍微修改@vault上面的答案(这可能是一个新功能)。用自然名称来指代该领域绝对是可取的。但是,我并没有覆盖
Manager
,而是简单地使用ForeignKey
的to_field
参数:fjaof16o2#
正如@gareth的answer所暗示的那样,硬编码默认的
id
值可能并不总是最好的主意:如果
id
值在数据库中不存在,那么您就有麻烦了。即使该特定id
值确实存在,对应的对象也可能发生变化。在任何情况下,当使用硬编码的id
值时,您都必须求助于数据迁移或手动编辑现有数据库内容之类的事情。为了防止这种情况,您可以将get_or_create()与
unique
字段(而不是id
)结合使用。这里有一个方法:
这里,
Exam.title
字段用于获取唯一对象,Exam.description
字段说明了如何使用defaults
参数(对于get_or_create
)来完全指定默认的Exam
对象。请注意,我们返回一个
pk
,如文档所建议的:对于像
ForeignKey
这样Map到模型示例的字段,默认值应该是它们引用的字段的值(pk
,除非设置了to_field
),而不是模型示例。还要注意,
default
可调用在Model.__init__()
(源代码)中进行计算。因此,如果您的默认值依赖于同一模型的另一个字段,或者依赖于请求上下文,或者依赖于客户端表单的状态,您可能应该查看elsewhere。xmakbtuz3#
我使用自然键来采用更自然的方法:
<app>/models.py
umuewwlo4#
在我的例子中,我希望将默认值设置为相关模型的任何 * 现有 * 示例。因为有可能id为
1
的Exam
已被删除,所以我执行了以下操作:如果
exam_taken
不存在,则在尝试访问它时将引发django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist
。wyyhbhjk5#
大多数方法的问题是它们在Model中使用了HARD CODED值或lambda方法,这些方法自Django 1.7版以来不再支持。
在我看来,这里最好的方法是使用sentinel方法,它也可以用于
on_delete
参数。所以,如果是你,我会
现在,当您刚刚添加
exam_taken
字段时,使用保证的现有值,同时在删除检查时,学生本身不会被删除,并且具有deleted
值的外键。rqmkfv5c6#
你可以使用这个模式:
当然,您需要确保
Other
表中有一行。您应该使用数据迁移来确保它存在。fhg3lkii7#
您需要在
get_exam()
中使用get_or_create(),在models.ForeignKey()中使用on_delete(),如下所示。* 不要忘记将.id
放在get_or_create(id=1)[0]
之后,因为models.ForeignKey()
中的默认值需要Exam
对象的id
,否则会出现错误,您可以看到我的答案解释get_or_create()
:并且,您可以将
get_exam()
放入Student
类中,如下所示:我建议在
Student
类中对get_exam()
使用@classmethod
,如下所示,以便其他类也可以通过类名使用get_exam()
。*@classmethod
可以做的事情比@staticmethod
多,根据我的回答:而不是
get_exam
,您可以将get_exam()
分配给default
,如下所示:31moq8wy8#
我在Django Admin中寻找解决方案,然后我发现了这个:
这也允许我使用当前用户。
查看Django文档
vwkv1x7d9#
我所知道的最好的方法就是使用lambda表达式
以便您可以指定默认行。