Login

Rails-like MVC Controllers for Django

Author:
sciyoshi
Posted:
November 18, 2008
Language:
Python
Version:
1.0
Score:
1 (after 1 ratings)

See the blog entry

Allows using controllers for views.

This allows for nice subclassing to override behavior of views. Controller.urls (see below) works fine for subclasses as well.

Similar to snippet #1165 except that it won't break reverse URL resolving and regex validation in URLs.

In views.py:

import mvc

class MyController(mvc.Controller):
   @mvc.view('myview/$', 'myview')
   def my_view(self):
       # do something with self.request
       return HttpResponse('something')

   class Meta(mvc.Controller.Meta):
       url_prefix = 'mycontroller-'

In urls.py:

from . import views

urlpatterns = patterns('',
    # ... other urls here ...
    *views.MyController.urls(r'prefix/')
)

Then the view MyController.my_view will be accessible from 'prefix/myview/' and have the name 'mycontroller-myview', i.e. reverse('mycontroller-myview') will work as expected.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
"""
Helpers for coding in a more MVC-fashion using Controller classes as opposed
to views.
"""

from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required

def view(path=None, name=None):
    def decorator(func):
        func.view = True
        func.name = name if name is not None else func.__name__
        func.path = path if path is not None else '^%s/$' % func.name
        return func
    return decorator

class ControllerMetaclass(type):
    @property
    def _meta(self):
        return self.Meta

    def urls(self, path_prefix=''):
        return [
            (path_prefix + view.path, self.get_handler(view), {}, self._meta.url_prefix + view.name)
        for view in (getattr(self, name) for name in dir(self)) if getattr(view, 'view', False)]

class Controller(object):
    __metaclass__ = ControllerMetaclass

    def __init__(self, request, *args, **kwargs):
        self.request = request

    @classmethod
    def get_view(cls, view, request, *args, **kwargs):
        return view(cls(request), *args, **kwargs)

    @classmethod
    def get_handler(cls, view):
        def inner(request, *args, **kwargs):
            return cls.get_view(view, request, *args, **kwargs)
        return reduce(lambda func, dec: dec(func), cls._meta.decorators, inner)

    class Meta(object):
        url_prefix = ''
        decorators = []

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

Please login first before commenting.