以下内容似乎没有区别:
ModelA.objects.filter(modelb_id=a_model_id)
ModelA.objects.filter(modelb=a_model_id)
打印出两种情况下Django生成的SQL都表明它是相同的。但是,我在任何地方都找不到官方记录的文档,因此,我担心在某些情况下仅使用modelb
可能会导致与modelb_id
有所不同。
我特别感兴趣的是有人向我指出可以确认这些内容相同的官方消息。
答案 0 :(得分:2)
TLDR:最好考虑框架作者的建议并使用模型字段名称。
数据库表示形式
在后台,Django将“ _id”附加到字段名称以创建其数据库列名称。在上面的示例中,Car模型的数据库表将具有一个制造商ID列。 (您可以通过指定db_column显式更改此设置。)但是,除非编写自定义SQL,否则您的代码永远不必处理数据库列名。您将始终处理模型对象的字段名称。 Reference
模型字段子类django.db.models.fields.Field
。 Field
类具有一个attname
字段,该字段是documented internally in the source code,用于解析要在模型对象上使用的属性。
# A guide to Field parameters:
#
# * name: The name of the field specified in the model.
# * attname: The attribute to use on the model object. This is the same as
# "name", except in the case of ForeignKeys, where "_id" is
# appended.
# * db_column: The db_column specified in the model (or None).
# * column: The database column for this field. This is the same as
# "attname", except if db_column is specified.
#
# Code that introspects values, or does other dynamic things, should use
# attname. For example, this gets the primary key value of object "obj":
#
# getattr(obj, opts.pk.attname)
作为执行converting the QuerySet.filter
names in the kwargs for the compiled SQL query的一部分,将名称转换为包含相应名称的模型字段的PathInfo
元组。
On Line 1354 for django.db.models.sql.query.Query
,是以下行:
field = opts.get_field(name)
现在opts
是django.db.models.options.Options
的实例,并且get_field
方法委托给_forward_fields_map
或fields_map
缓存的属性。
当您查看这两个属性的实现时,您会看到它们返回从field.name
到field
到field.attname
到field
的字典映射。
这使得modelb_id
或modelb
从任一缓存的属性解析为模型字段。
我认为,将modelb_id
或modelb
作为关键字参数传递给QuerySet.filter
并不重要。只有前一个关键字需要了解实现细节。
但是最好考虑框架作者的建议并使用模型字段名称。