Get yourself a better Django proxy experience

Ah, Django proxy models and the power they hold! Yet, the implementation aftermath can highlight a number of unwanted side-effects. Here’s a couple of tips when working with Django proxies that will make end-users grateful and developers sigh in relief.

No more toe-curling results from ORM queries

Initialize discriminating proxy model fields to their expected values. You’ll see the benefits of this tip when unit-testing proxy instances already, where you should be using to speed up your tests and straight proxy model queries to shorten your ORM statements.

Start with overriding the main queryset method in :

from django.db.models import manager
class ParentProxyModelManager(manager.Manager):
"""The parent proxy model manager."""
def get_queryset(self):
"""Return the queryset."""
return super().get_queryset().filter(
discriminating_field=self.model.DISCRIMINATING_FIELD
)

In :

from django.db import Model
class ParentModel(models.Model):
"""The parent model."""
# Add your proxy-discriminating field(s) here
class ParentProxyModel(ParentModel):
"""The parent proxy model."""
DISCRIMINATING_FIELD = None objects = ParentProxyModelManager()

class Meta:
"""Model options."""

proxy = True

def __init__(self, *args, **kwargs):
"""Initialize proxy instance."""
super().__init__(*args, **kwargs)
self.discriminating_field = self.DISCRIMINATING_FIELD

Sensible link behaviour in the parent changelist

Sometimes you want to keep showing the proxy parent model admin for listing all the results. One issue with this is that every instance link in the changelist still points to its non-proxified version. You will see how problematic this ends up being if not corrected as your proxy modeladmins grow in behavioral diversity. What we can do is add a method to our model returning the right proxy and override in the proxy parent admin model.

In :

from django.db import Modelclass ParentModel(models.Model):
"""The parent model."""
... def get_proxy_model(self):
"""Return the proxy model."""
# Check those fields' values discriminating your proxy model
# and return the latter

In :

from django.contrib import admin
from django.http import HttpResponseRedirect
@admin.register(ParentModel)
class ParentModelAdmin(admin.ModelAdmin):
"""The parent model admin."""
fields = ("discriminating_field",) def change_view(
self,
request,
object_id,
form_url="",
extra_context=None
):
"""Return the change view."""
if self.model.__name__ == "ParentModel":
obj = self.get_object(request, object_id)
proxy = obj.get_proxy_model()
if proxy._meta.model.__name__ != "Operation":
redirect_url = reverse(
(
f"admin:{proxy._meta.app_label}_"
f"{proxy._meta.model_name}_change"
),
kwargs={"object_id": obj.pk},
)
return HttpResponseRedirect(redirect_url)
return super().change_view(
request, object_id, form_url, extra_context
)

As you can see, it doesn’t take that much to make Django proxy models better. Find here the official documentation on the general subject.

Philosophy grad specialised in Journalism and Computer Science, working in product development.