Django: extend get_object for class-based views

Gregor picture Gregor · Jul 22, 2011 · Viewed 7.1k times · Source

Being a non-expert Python programmer, I'm looking for feedback on the way I extended the get_object method of Django's SingleObjectMixin class.

For most of my Detail views, the lookup with a pk or slugfield is fine - but in some cases, I need to retrieve the object based on other (unique) fields, e.g. "username". I subclassed Django's DetailView and modified the get_object method as follows:

# extend the method of getting single objects, depending on model
def get_object(self, queryset=None):

    if self.model != mySpecialModel:
        # Call the superclass and do business as usual 
        obj = super(ObjectDetail, self).get_object()
        return obj

    else:
        # add specific field lookups for single objects, i.e. mySpecialModel
        if queryset is None:
            queryset = self.get_queryset()

        username = self.kwargs.get('username', None)
        if username is not None:
            queryset = queryset.filter(user__username=username)
        # If no username defined, it's an error.
        else:
            raise AttributeError(u"This generic detail view %s must be called with "
                                 u"an username for the researcher."
                                 % self.__class__.__name__)

        try:
            obj = queryset.get()
        except ObjectDoesNotExist:
            raise Http404(_(u"No %(verbose_name)s found matching the query") %
                          {'verbose_name': queryset.model._meta.verbose_name})
        return obj

Is this good practise? I try to have one Subclass of Detailview, which adjusts to differing needs when different objects are to be retrieved - but which also maintains the default behavior for the common cases. Or is it better to have more subclasses for the special cases?

Thanks for your advice!

Answer

Bernhard Vallant picture Bernhard Vallant · Jul 22, 2011

You can set the slug_field variable on the DetailView class to the model field that should be used for the lookup! In the url patterns it always has to be named slug, but you can map it to every model field you want.

Additionally you can also override the DetailView's get_slug_field-method which only returns self.slug_field per default!