2
\$\begingroup\$

A working example of mine, trying to streamlining my Django views, with absolute inspiration from Laravel:

class BaseController(View):
    template_404 = "404.html"

    def __call__(self, *args, **kwargs):
        return self.view(*args, **kwargs)

    def view(self, request, slug=None):
        method = request.method.lower()
        if hasattr(self, method):
            return getattr(self, method)(request, slug)
        return self.forbidden(request)

    def get(self, request, slug):
        if slug is not None:
            return getattr(self, "show")(request, slug) if hasattr(self, "index") else self.forbidden(request)
        return getattr(self, "index")(request) if hasattr(self, "index") else self.forbidden(request)

    def post(self, request, slug):
        return getattr(self, "store")(request) if hasattr(self, "store") else self.forbidden(request)

    @staticmethod
    def forbidden(request):
        return HttpResponseForbidden("Method not allowed")

    def page_not_found(self, request):
        return render(request, self.template_404)

Inherited by:

class EulerController(BaseController):
    template_name_index = "euler_index.html"
    template_name_show = "euler_show.html"

    def index(self, request):
        euler_posts = EulerPost.objects.all()
        return render(request, self.template_name_index, {"euler_posts": euler_posts})

    def show(self, request, slug):
        euler_post = EulerPost.objects.filter(slug=slug).first()
        return render(request, self.template_name_show, {"euler_post": euler_post})

and called by:

urlpatterns = [
    url(r'^$', EulerController(), name='main'),
    url(r'^(?P<slug>[\w-]+)/$', EulerController(), name='resource'),
]

and the mock model:

class EulerPost(model):
    slug = models.CharField(default=None, max_length=200, blank=False, unique=True)

I left Django for PHP-Laravel, long ago believing myself to be an to unstructured for the freedom of Django. But now I feel I am on the right track.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

It is usually better to ask forgiveness than permission and explicit is better than implicit. So I would change your getattr..if hasattr to a try..except, which is a lot easier to understand:

def post(self, request, slug):
    try:
        return self.store(request)
    except AttributeError:
        raise HttpResponseForbidden("Method not allowed")

And similar for get and view:

def get(self, request, slug):
    try:
        if slug is not None:
            return self.show(request, slug)
        return self.index(request)
    except AttributeError:
        raise HttpResponseForbidden("Method not allowed")

def view(self, request, slug=None):
    try:
        return getattr(self, request.method.lower())(request, slug)
    except AttributeError:
        raise HttpResponseForbidden("Method not allowed")
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.