Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard way of replacing urlpatterns with view decorators in django?

I've developed my own, but it seems like it's a great enough thing that someone else probably thought of it first and did a better job ;)

The goal is to be able to write, in your myapp/views.py

router = Router(prefix=r'^myapp/')

@router.route(url=r'my/url/here', name="my-great-view")
def myview(request):
    return render_to_response("mytemplate.html", {})

And then in urls.py

urlpatterns += myapp.views.router.get_patterns()

And there are several other cool decorator things I've built in (@jsonview for taking a returned dictionary and making a json response, @use_template for taking a returned dictionary and passing it to the defined template as the context...)

It seems like this way makes everything a lot more localized an readable. When looking at a view function you don't have to search around to find what url it belongs to, or what it's "named".

I saw this one djangosnippet, but it's a lot more magic than I'd like, and it doesn't look like it's been generally adopted.

In the event that no one has put together a standard solution, should I clean mine up and submit a pull request to contrib?

  • here is what I currently have implemented: magic.py

Edit: if you want multiple urls for the same view:

@router.route(url="my-first-url", kwargs={'foo':'bar'})
@router.route(url="my-second=url", kwargs={'foo':'baz'})
def my_view(...): ...

And of course this doesn't have to be the only way to do it -- the normal urlpatterns way has some nice things about it two, but these two methods are not mutually exclusive.

like image 445
Jared Forsyth Avatar asked Jan 15 '13 17:01

Jared Forsyth


2 Answers

The regular configuration we have a main website urls.py . And the urls.py contains variable named urlpatterns.

so wo can push some url_pattern into it.

app/views.py

from django.urls import path as djpath

URLS = []
URLS_d = {}


def route(path=''):
    def wrapper(func):
        path_name = path or func.__name__
        URLS.append(
            djpath(path_name, func)
        )

        ### below is not important ####
        path_func = URLS_d.get(path_name, None)
        if path_func:
            print(path_func, '<>', func)
            raise Exception('THE same path')
        URLS_d[path_name] = func
        ### above is not important ####

    return wrapper

@route()
def index(req):
    return HttpResponse('hello')

website/urls.py

from app.views import URLS

urlpatterns.extend(URLS)
like image 102
dick Avatar answered Sep 28 '22 00:09

dick


If you use class base view , you can use django-request-mapping,

A Simple Example
  • view.py
from django_request_mapping import request_mapping


@request_mapping("/user")
class UserView(View):

    @request_mapping("/login/", method="post")
    def login(self, request, *args, **kwargs):
        return HttpResponse("ok")

    @request_mapping("/signup/", method="post")
    def register(self, request, *args, **kwargs):
        return HttpResponse("ok")

    @request_mapping("/<int:user_id>/role/")
    def get_role(self, request, user_id):
       return HttpResponse("ok") 

    @request_mapping("/<int:pk/", method='delete')
    def delete(self, request, pk):
        User.objects.filter(pk=pk).delete()
        return HttpResponse("ok")


@request_mapping("/role")
class RoleView(View):
    # ...

  • urls.py
from django_request_mapping import UrlPattern
urlpatterns = UrlPattern()
urlpatterns.register(UserView)
urlpatterns.register(RoleView)

and request urls are:

post:  http://localhost:8000/user/login/
post:  http://localhost:8000/user/signup/
get:  http://localhost:8000/user/1/role/
delete: http://localhost:8000/user/1/
# ...
like image 23
pagala2008 Avatar answered Sep 28 '22 01:09

pagala2008