8

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!

Gregor
  • 95
  • 2
  • 4

2 Answers2

10

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!

Bernhard Vallant
  • 49,468
  • 20
  • 120
  • 148
  • 2
    Thanks! Totally missed this part, was thrown off by the comments in get_object: `By default this requires "self.queryset" and a "pk" or "slug" argument in the URLconf, but subclasses can override this to return any object.` – Gregor Jul 22 '11 at 12:09
  • 7
    AS everybody knows documentation on generic class based views is somewhere between bad and evil. – Bernhard Vallant Jul 22 '11 at 12:48
0

Can you use inheritance?

class FooDetailView(DetailView):
    doBasicConfiguration

class BarDetailView(FooDetailView):
    def get_object(self, queryset=None):
        doEverythingElse
AA.
  • 4,496
  • 31
  • 35