Question

Im trying to make a url setup that would display a detail page based on just a year (not month and day), and a pk. like this /YEAR/ISSUE/

This is what I have tried:

My model.py:

class Mag(models.Model):
    name = models.CharField(max_length=500)
    issue = models.PositiveIntegerField()  
    pub_date = models.DateTimeField()


    unique_together = ("pub_date", "issue")

    def __unicode__(self):
        return self.name        

    @models.permalink        
    def get_absolute_url(self):
            creation_date = timezone.localtime(self.pub_date)
            return ('mag_detail', (), {
                'year': creation_date.strftime('%Y'),
                'pk': self.issue})

My views.py:

class MagDetail(DateDetailView):

    model = Mag
    pk_url_kwarg='pk'
    date_field='pub_date'

My urls.py

urlpatterns = patterns('',
    url(r'^(?P<year>\d{4})/(?P<pk>\d+)/$', MagDetail.as_view(), name='mag_detail'),
)

But when I try a url like 2014/1, I get an error that month is not specified.

Is it possible to do what I want with DateDetailView, or do I need to look another class?

Was it helpful?

Solution

What if you use a standard DetailView and override the get_object() method, like this:

from django.shortcuts import get_object_or_404

class MagDetail(DetailView):
    model = Mag

    def get_object(self):

        obj = get_object_or_404(
            self.model, 
            pk=self.kwargs['pk'], 
            pub_date__year=self.kwargs['year'])

        return obj

OTHER TIPS

The DateDetailView expects the format of year/month/day

As a general approach, if you will be using this kind of view in your project for other models than Mag alone, you can derive from it though and change the get_object method, roughly like that:

class YearDetailView(DateDetailView):
    def get_object(self, queryset=None):
        """
        Get the object this request displays.
        """
        year = self.get_year()

        # Use a custom queryset if provided
        qs = queryset or self.get_queryset()

        if not self.get_allow_future() and int(year) > datetime.today().year:
            raise Http404(_("Future %(verbose_name_plural)s not available because 
                            %(class_name)s.allow_future is False.") % {
                                'verbose_name_plural': qs.model._meta.verbose_name_plural,
                                'class_name': self.__class__.__name__,
                          })

        lookup_args = {"%s__year" % self.get_date_field(): year}
        qs = qs.filter(**lookup_args)

        return super(BaseDetailView, self).get_object(queryset=qs)

class MagDetail(YearDetailView): # note that we derive from our new class!
    model = Mag
    pk_url_kwarg='pk'
    date_field='pub_date'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top