class GenericForeignKey
There are three parts to setting up a GenericForeignKey
:
- Give your model a
ForeignKey
toContentType
. 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
. The usual name for this field is “object_id”. - Give your model a
GenericForeignKey
, and pass it the names of the two fields described above. If these fields are named “content_type” and “object_id”, you can omit this – those are the default field namesGenericForeignKey
will look for.
-
for_concrete_model
-
If
False
, the field will be able to reference proxy models. Default isTrue
. This mirrors thefor_concrete_model
argument toget_for_model()
.
Primary key type compatibility
The “object_id” field doesn’t have to be the same type as the primary key fields on the related models, but their primary key values must be coercible to the same type as the “object_id” field by its get_db_prep_value()
method.
For example, if you want to allow generic relations to models with either IntegerField
or CharField
primary key fields, you can use CharField
for the “object_id” field on your model since integers can be coerced to strings by get_db_prep_value()
.
For maximum flexibility you can use a TextField
which doesn’t have a maximum length defined, however this may incur significant performance penalties depending on your database backend.
There is no one-size-fits-all solution for which field type is best. You should evaluate the models you expect to be pointing to and determine which solution will be most effective for your use case.
Serializing references to ContentType
objects
If you’re serializing data (for example, when generating fixtures
) from a model that implements generic relations, you should probably be using a natural key to uniquely identify related ContentType
objects. See natural keys and dumpdata --natural-foreign
for more information.
This will enable an API similar to the one used for a normal ForeignKey
; each TaggedItem
will have a content_object
field that returns the object it’s related to, and you can also assign to that field or use it when creating a TaggedItem
:
>>> from django.contrib.auth.models import User >>> guido = User.objects.get(username='Guido') >>> t = TaggedItem(content_object=guido, tag='bdfl') >>> t.save() >>> t.content_object <User: Guido>
Due to the way GenericForeignKey
is implemented, you cannot use such fields directly with filters (filter()
and exclude()
, for example) via the database API. Because a GenericForeignKey
isn’t a normal field object, these examples will not work:
# This will fail >>> TaggedItem.objects.filter(content_object=guido) # This will also fail >>> TaggedItem.objects.get(content_object=guido)
Likewise, GenericForeignKey
s does not appear in ModelForm
s.
Please login to continue.