1

I've got a 'Registration' object in place that users can create on the front end without issue.

It looks like this:

class Registration(models.Model):
    person = models.ForeignKey(Person, on_delete=models.PROTECT)
    course_detail = models.ForeignKey(CourseDetail, on_delete=models.PROTECT)
    camp_shirt = models.ForeignKey(CampShirt, on_delete=models.PROTECT)
    comments = models.CharField(max_length=200, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return "%s" % (self.course_detail.course.camp)

When I am in the admin and click on a given Registration - it takes a while to load because there are thousands and thousands of Person objects.

For ease of use - there will never be a time when we would need to edit the 'person' associated with a given registration, so I would like to make the 'person' dropdown only show the selected user in the person queryset when editing from the django admin.

So when I go to http://myapp.com/admin/registration/23/change I want the form to only display the currently selected person as the only option in the dropdown.

My admin model looks like this:

class RegistrationAdmin(admin.ModelAdmin):
    list_display = ("person", "course_detail")

    class Meta:
        # I think this is what I do in order to override the default admin form? Not sure.
        form = RegistrationAdminForm

My RegistrationAdminForm looks like this:

class RegistrationAdminForm(forms.ModelForm):
    # course_detail, person, camp_shirt, comments
    person = forms.ModelChoiceField(queryset=Person.objects.filter(
        id=registration.person.id)
    )

    def __init__(self, registration, *args, **kwargs):
        super(RegistrationAdminForm, self).__init__(*args, **kwargs)
        self.fields['person'].queryset = Person.objects.filter(
            id=registration.person.id
        )

    class Meta:
        model = Registration
        fields = '__all__'

Main Question : How do I change the admin form so that a specific queryset is returned for one of the fields in the django admin?

Hanny
  • 580
  • 3
  • 16
  • 44

1 Answers1

2

If the person field will never be changed you can add the person field to readonly_fields, a select with all Person objects will not be rendered.

class RegistrationAdmin(admin.ModelAdmin):
    list_display = ("person", "course_detail")
    readonly_fields = ("person", )

Then you do not need your custom form. FYI when you want to add a custom form to a ModelAdmin you do not put it in Meta, you define it on the form itself

class MyModelAdmin(admin.ModelAdmin):
    form = MyModelForm
Iain Shelvington
  • 31,030
  • 3
  • 31
  • 50
  • If I wanted to limit some of the other options (dropdowns) to a particular queryset, will what I have there work to help accomplish this? By the way - for that particular thing (`person`) this worked great. – Hanny Nov 06 '19 at 12:31