Kedare
Kedare

Reputation: 1277

Set a custom queryset (select_related) for a list field in the admin change page?

I have an using the Django admin interface to manage a lot of objects, and one of the page is giving me issue, this page has a field to a related object (Foreign Key) that has a __str__ that also goes to its related objects, this make a lot of queries and is barely useable (Around 3000 queries to show the page as there are a LOT of objects).

I would like to know if there is a way to set a custom queryset ? I would like to add a select_related or prefetch_related to this element.

The part causing issue is this certificate requests list :

enter image description here

The page model (Certificate has the following attribute:

class Certificate(models.Model):

    certificate_request = models.OneToOneField(
        "CertificateRequest",
        verbose_name=_("Certificate request"),
        related_name="certificate",
        blank=True,
        null=True
    )

And the related model has this :

class CertificateRequest(models.Model):

    domain = models.ForeignKey(
        "Domain",
        verbose_name=_("Domain"),
        related_name="certificate_requests"
    )

    def __str__(self):
        return "{state} certificate request for {domain} from {creation_date}".format(
            state=dict(self.STATUS).get(self.status),
            domain=self.domain.fqdn,
            creation_date=self.creation_date
        )

What would be the way to fix this ? How can I set a queryset on this part ?

EDIT: I added more informations. I tried using a custom form, but this didn't do any change :

class CertificateForm(forms.ModelForm):
    certificate_request = forms.ModelChoiceField(queryset=CertificateRequest.objects.select_related("domain"))

    class Meta:
        model = Certificate
        fields = "__all__"


@admin.register(Certificate)
class CertificateAdmin(CompareVersionAdmin):
    model = Certificate

    class Meta:
        form = CertificateForm

Upvotes: 1

Views: 2881

Answers (2)

user2390182
user2390182

Reputation: 73498

You can create a custom ModelForm for your admin where you specify a ModelChoiceField for the ForeignKey. Here you can specify the queryset parameter:

# forms.py
class MyForm(forms.ModelForm):
    certificate_request = forms.ModelChoiceField(queryset=CertReq.objects.foo().bar())
    #                                               select/prefetch-------^^^^^^^^^^^

    class Meta:
        model = Foo

# admin.py
class YourAdmin(ModelAdmin):
    form = MyForm

Upvotes: 2

Daniel Roseman
Daniel Roseman

Reputation: 599956

The get_object method on the ModelAdmin class is what is responsible for retrieving the object to edit. You could certainly extend that method in your subclass to use select_related as necessary.

Upvotes: -1

Related Questions