How can I restrict Django's GenericForeignKey to a list of models?

15,075

For example, your apps are app and app2 and there are A, B models in app and there are C, D models in app2. you want to see only app.A and app.B and app2.C

from django.db import models

class TaggedItem(models.Model):
    tag = models.SlugField()
    limit = models.Q(app_label = 'app', model = 'a') | models.Q(app_label = 'app', model = 'b') | models.Q(app_label = 'app2', model = 'c')
    content_type = models.ForeignKey(ContentType, limit_choices_to = limit)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

use limit_choices_to on ForeignKey.

check django docs for details and Q objects, app_label. you need to write proper app_label and model. This is just code snippet

plus: I think you write wrong app_label. This can help you.

from django.contrib.contenttypes.models import ContentType
for c in ContentType.objects.all():
    print(c.app_label, c.model)
Share:
15,075
MarkD
Author by

MarkD

Updated on June 18, 2022

Comments

  • MarkD
    MarkD almost 2 years

    Is there a way of telling django that a model having a contenttypes GenericForeignKey can only point to models from a predefined list? For example, I have 4 models: A, B, C, D and a model X that holds a GenericForeignKey. Can I tell X that only A & B are allowed for the GenericForeignKey?

  • MarkD
    MarkD almost 13 years
    But, the admin interface doesn't seem to use this, for it's choice field. Why is that?
  • mumino
    mumino almost 13 years
    I checked it on admin side and it works with default admin, as expected. maybe you did some little typo there. I don't know your problem.
  • MarkD
    MarkD almost 13 years
    On my admin, after I add your limit, the choices from the GenericForeignKey's select disappear. I'm only left with "---". Could you please post a screenshot with your admin's select choices?
  • mumino
    mumino almost 13 years
    I think you write wrong app_label or model. app_label and model must be lowercase. check my answer, I added some more info.
  • MarkD
    MarkD almost 13 years
    You are right. I had the model names wrong. Perhaps you could have a look at stackoverflow.com/questions/6335565/… too?
  • shad0w_wa1k3r
    shad0w_wa1k3r over 4 years
    Works for me on Django 2.2. Important point to note here is that this limiting / restriction only applies to django admin selection dropdowns / views, it does not enforce database constraints as such. So you can assign different content types via code in spite of the limit_choices_to parameter. You may try and override the save method for validating content types at code level.
  • kloddant
    kloddant about 4 years
    For clarity here, I would not lump the limit variable in with the list of model fields. It should probably be above the list with a blank line or two in between.