Mihai Zamfir
Mihai Zamfir

Reputation: 2166

Django class based views example

I can't understand the class based views, so I am trying to figure it out with an example. Here is what I have so far:

#urls.py
url(r'^(?P<langcode>[a-zA-Z-]+/about/$', about, name='about')


#views.py
def about(request, langcode):
    languages = Language.objects.values_list('code', flat=True)
    language = get_object_or_404(Language, pk=langcode)
    return render(request, 'about.html', {
        'languages': languages,
        'language': language
    })

I also have some other functional views which contain the first 2 lines of about:

languages = Language.objects.values_list('code', flat=True)
language = get_object_or_404(Language, pk=langcode)

So, what I want to do now is:

  1. create a class BaseView (or however you want to call it) which extends something from django.generic.views and which will determine the language and languages parameters for the context based on the langcode input parameter

  2. Create the class AboutView(BaseView) (so extending the BaseView) which will somehow define the template name about.html to be used for rendering.

  3. I will further have another class based view, also to extend BaseView and which is simillar to AboutView, but which sets one more context parameter called region depending as well on the langcode input parameter

Can someone show me exactly how to code this stuff? thank you

Upvotes: 1

Views: 1864

Answers (1)

Gabriel Amram
Gabriel Amram

Reputation: 2790

Here's a simple way to achieve what you want:

You first define the common logic, using the TemplateView generic view:

class MyBaseView(TemplateView):
    def dispatch(self, request, *args, **kwargs):
        # dispatch takes care of "reading" the parameters from the url
        self.language = get_object_or_404(Language, pk=kwargs.pop("langcode")) # I would use some kind of default value to prevent exception, but its up to your logic
        return TemplateView.dispatch(self, request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        # get_context_data creates the context
        context = TemplateView.get_context_data(self, **kwargs)
        context.update({"language": self.language, 
                        "languages": Language.objects.values_list('code', flat=True)})

        return context

Then, you don't even need an AboutView because all you want is to control the template_name, so in your urls.py:

# in urls,py you can just use this, instead of defining an AboutView, you pass the template_name you want to use, this is sufficient because TemplateView expects a template_name attribute
url('^(?P<langcode>[a-zA-Z]+)/about/$', MyBaseView.as_view(template_name="about.html"), name='about')

and finally, for the other view that uses region you can just inherit from the MyBaseView, and add the context you want:

class AboutViewWithRegion(MyBaseView):
    def get_context_data(self, **kwargs):
        context = MyBaseView.get_context_data(self, **kwargs)
        context.update({"region": <<your logic here>>})
        return context

Hope that helps!

Upvotes: 2

Related Questions