在我的模型中,我有一个Concert
类和一个Venue
类。每个场地都有多场音乐会。我一直用一个简单的
venue = models.IntegerField(max_length = 10)
...包含场地对象的主键。一位同事建议我们改用venue = models.ForeignKey(Venue)
。虽然这也有效,但我想知道是否值得转换,因为我能够通过简单地在Concert.objects.filter(venue=4)
中使用场地ID来解析场地的所有音乐会,就像我用{{1}那样做}:ForeignKey
。我使用我的方法时从来没有遇到任何问题。
我看到它的方式,使用Venue_instance.Concert_set.all()
和IntegerField
与objects.filter()
的“ManyToOne”关系一样多,所以我想知道我哪里错了。为什么ForeignKey
有利?它们更快吗?它是更好的数据库设计吗?清洁代码?
答案 0 :(得分:3)
我想说外键最实用的好处是能够自动查询关系。 Django自动生成JOIN。
你提到的自动反向关系助手也很棒。
以下是一些只有整数关系会更复杂的例子。
concerts = Concert.objects.filter(...)
concerts.order_by('venue__attribute') # ordering beyond PK.
concerts.filter(venue__name='foo') # filter by a value across the relationship
concerts.values_list('venue__name') # get just venue names
concerts.values('venue__city').annotate() # get unique values across the venue
concerts.filter(venue__more__relationships='foo')
Venue.objects.filter(concert__name='Coachella') # reverse lookups work too
# with an integer field for Concert.venue, you'd have to do something like...
Venue.objects.filter(id__in=Concert.objects.filter(name='Coachella'))
正如其他人指出的那样......数据库完整性很有用,级联删除(当然可以自定义)和 facepalm 我刚刚想到django管理员和表单框架使用外键工作得非常好。
class ConcertInline(admin.TabularInline):
model = Concert
class VenueAdmin(admin.ModelAdmin):
inlines = [ConcertInline]
# that was quick!
我确信有更多django功能处理外键的例子。
答案 1 :(得分:3)
ForeignKey是大多数数据库中实施的database concept,也强制执行referential integrity。
因为django会知道这个列引用的是一个表,它本身可能是某个其他表的外键,它可以帮助链接将在SQL中产生相应连接的关系。
除了正常的单向链接之外,Django还向对方添加了一个参数,就像你已经认识到的那样。当您拥有场地实例时,您可以查询venue.concert_set
。
最让我烦恼的是不使用FK并使用整数滚动自己的东西: