I've been trying to display a GenericForeignKey
in the Django admin but can't get it working. I have a FullCitation
class that can be linked to either a NonSupportedProgram
or a SupportedProgram
class. So, I have used a generic foreign key.
In the admin, I want users to only be able to select 'NonSupportedProgram'
or 'SupportedProgram'
from the content_type
dropdown and then, from the object_id
field, I need users to be able to select from a dropdown listing the existing NonSuportedProgram
s or the existing SupportedProgram
s, with the option of creating a new one. Is this possible? Where am I going wrong?
models.py
class FullCitation(models.Model)
# the software to which this citation belongs
# either a supported software program or a non-supported software program
limit = models.Q(app_label = 'myprograms', model = 'supportedprogram') | models.Q(app_label = 'myprograms', model = 'nonsupportedprogram')
content_type = models.ForeignKey(ContentType), limit_choices_to = limit, )
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
is_primary = models.BooleanField(help_text="Is this the Primary Citation for the software program?")
class Meta:
unique_together = ('content_type', 'object_id')
app_label = 'myprograms'
reversion.register(FullCitation)
class NonSupportedProgram(models.Model):
title = models.CharField(max_length=256, blank = True)
full_citation = generic.GenericRelation('FullCitation')
class Meta:
app_label = 'myprograms'
reversion.register(NonSBGridProgram)
class SupportedProgram(models.Model):
title = models.CharField(max_length=256, blank = True)
full_citation = generic.GenericRelation('FullCitation')
# and a bunch of other fields.....
admin.py
class FullCitationAdmin(reversion.VersionAdmin):
fieldsets = (
('Which Program', {
'fields': ('content_type', 'object_id', ),
}),
('Citation Information', {
'fields': ('is_primary',),
}),)
# autocomplete_lookup_fields = {
# 'generic': [['content_type', 'object_id']],
# }
# inlines = ['NonSupportedProgramInline', ]
list_display = ('content_object', 'is_primary',)
search_fields = ('content_object__title', )
# list_filter = ('content_object',)
To overcome this, Django's content types framework provides a special field type (GenericForeignKey) which allows the relationship to be with any model. Here is the solution for the above scenario. There are three parts to setting up a GenericForeignKey: Give your model a ForeignKey to ContentType.
There are three parts to setting up a GenericForeignKey: Give your model a ForeignKey to ContentType. The usual name for this field is “content_type”. Give your model a field that can store primary key values from the models you’ll be relating to.
Give your model a ForeignKey to ContentType. The usual name for this field is “content_type”. Give your model a field that can store primary key values from the models you’ll be relating to. For most models, this means a PositiveIntegerField.
Several of Django’s bundled applications make use of the latter technique. For example, the permissions system in Django’s authentication framework uses a Permission model with a foreign key to ContentType; this lets Permission represent concepts like “can add blog entry” or “can delete news story”.
This is a module that renders GenericForeignKeys in the Django Admin:
https://github.com/lexich/genericrelationview
It just doesn't work with a no conflict jQuery setup (like the one from Django CMS).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With