4

I've tried everything I can find on the internet here, and nothing seems to work, so wondering if lots of the previous answers are for old versions. I'm on Django 2.2.9.

#models.py

class ParentModel(models.Model):
   title = models.CharField()

class ChildModel(models.Model):
   parent = models.ForeignKey(
        ParentModel,
        on_delete=models.CASCADE,
        related_name='parent'
    )

# admin.py

@admin.register(ParentModel)
class ParentModelAdmin(admin.ModelAdmin):
    model = ParentModel

    def get_queryset(self, request):
        return ParentModel.objects.get_complete_queryset()


class ChildModelForm(forms.Form):
    def __init__(self, u, *args, **kwargs):
        super(ChildModelForm, self).__init__(*args, **kwargs)
        self.fields['parent'].queryset = ParentModel.objects.get_complete_queryset()

    class Meta:
        model = ChildModel
        fields = '__all__'


@admin.register(ChildModel)
class ChildModelAdmin(admin.ModelAdmin):
   model = ChildModel
   form = ChildModelForm

   def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "parent":
            kwargs["queryset"] = ParentModel.objects.get_complete_queryset()

        return super().formfield_for_foreignkey(db_field, request, **kwargs)

I have a manager query called get_complete_queryset on ParentModel that returns a broader set of Parents than the default queryset.

The setup above allows me to go to my ChildModelAdmin and select the 'hidden' Parents from the dropdown, but when I try and save it gives me this error:

parent instance with id 2 does not exist.

There must be some queryset the form is using to save the model that isn't overridden, but I can't find what it is.

MDalt
  • 1,681
  • 2
  • 24
  • 46

2 Answers2

3

You can override get_form method like this:

def get_form(self, request, obj, **kwargs):
        form = super(<YourModelAdmin>,self).get_form(request, obj, **kwargs)
        form.base_fields['<you_field>'] = forms.ModelChoiceField(queryset=<your_queryset>)
        return form
  • Unfortunately, this method will not work if you ever need to add a new object to the ChoiceField. It won't recognize it whenever you save due to the new object not being part of the query. – user3605767 Dec 31 '22 at 03:11
0

You can write your custom ModelAdmin class, and thereafter you override the predefined get_form function

from django.contrib import admin

@admin.register(YourModel)
class YourModelAdmin(admin.ModelAdmin):
  def get_form(self, request, obj, **kwargs):
    form = super(YourModelAdmin,self).get_form(request, obj, **kwargs)
    form.base_fields['<yourColumn>'].queryset=<Your custom Queryset here>
    return form
NINSIIMA WILBER
  • 159
  • 1
  • 7