Я бы сказал, что наиболее практичным преимуществом внешнего ключа является возможность автоматически запрашивать отношения. Django генерирует соединения автоматически.
Как вы уже упоминали, помощники автоматического обратного отношения тоже хороши.
Вот несколько примеров, которые были бы более сложными только с целочисленными отношениями.
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, обрабатывающих внешние ключи.