This commit is contained in:
Víðir Valberg Guðmundsson 2023-06-21 22:30:28 +02:00
parent e12a490497
commit af2c753e87

View file

@ -72,7 +72,7 @@ First we setup our project URLconf to include URLs from `django-view-decorator`:
path("", include_view_urls()),
]
Then we can use the `view` decorator like so (we dive deeper in what the decorator does later on):
Then we can use the `view` decorator like so:
:::python
# foos/views.py
@ -91,6 +91,8 @@ Even class-based views are supported:
class FooList(ListView):
model = Foo
Now that is what I call Locality of Behaviour!
## More advanced usage
Multiple URLs can point at the same view, and you might have noticed that the argument is the plural `paths`. This is because we can pass a list of paths which point at the same view. Like so:
@ -120,7 +122,7 @@ Multiple URLs can point at the same view, and you might have noticed that the ar
context=context
)
Looking at the view we can grok that it is exposed on two paths, under the `foos` namespace, one which lists all `Foo` objects and one which given an integer gives us the detail for a single `Foo`. That's pretty powerful if you ask me!
Looking at the view we can see that it is exposed on two paths, under the `foos` namespace, one which lists all `Foo` objects and one which given an integer gives us the detail for a single `Foo`.
If we want different names for each path we can simply apply the decorator multiple times:
@ -170,7 +172,9 @@ This would include views from `foos/special_views.py` in the registry.
## Namespaces and the power of factories
In our more advanced example you might have noticed the `namespace="foos"`, which probably is going to quite tedious to repeat over and over again. In vanilla Django URLconfs we get namespacing by using the `include` function. So how do we do namespacing with this new pattern?
In the advanced example you might have noticed the `namespace="foos"`, which is going to quite tedious to repeat over and over again.
In Django URLconfs we can do namespacing by using the `include` function. So how do we do namespacing with this new pattern?
This is where the aptly named `namespaced_decorator_factory` comes into the picture. Let us look at an example:
@ -194,7 +198,7 @@ This is where the aptly named `namespaced_decorator_factory` comes into the pict
By calling `namespaced_decorator_factory` we get a specialised decorator for our namespace and we can even provide it with a path which will be prepended to all URLs registered using it.
This opens up a quite nifty possibility of injecting URLs into a namespace from anywhere. For example:
This opens up a the possibility of injecting URLs into a namespace from anywhere. For example:
:::python
# app_1/views.py
@ -211,14 +215,16 @@ This opens up a quite nifty possibility of injecting URLs into a namespace from
name="custom-view"
)
def custom_view(request: HttpRequest) -> HttpResponse:
return HttpResponse("I'm a view in the app_1 namespace defined in another views file.")
return HttpResponse(
"I'm a view in the app_1 namespace."
)
Now we can treat `custom_view` as if it was a part of the `app_1` namespace. Ie. `reverse("app_1:custom-view")` would give us `app_1/my-custom-view/`. Neat!
### Namespaces for AppConfigs
In the process of writing this blog post and trying to figure out how all this could be implemented into Django, I came up with the idea to leverage the applications framework in Django to get a namespaced decorator for a given Django app.
While writing this blog post, and therefore trying to figure out how to implement this pattern in Django, I found that the application framework in Django is a great hook for creating namespaced decorators for apps. So `django-view-decorator` ships with its own `AppConfig` which can be used like so:
:::python
# foos/apps.py
@ -248,7 +254,7 @@ Newcomers would learn that to hook up views to URLs they register their views in
## The path to Django core
So, as I wrote initially, I have a mission to try to get this pattern into Django core. This is not going to be an easy feat, but I want to be upfront about my plan. Partly because I think it is going to enhance my chances of succeeding, but also so the current project can move in the right direction.
So, as I wrote initially, I have a mission to try to get this pattern into Django core. This is not going to be an easy feat, but I want to be upfront about my plan. Partly because I think it is going to enhance my chances of succeeding, but also so that the current project can move in the right direction.
To cite Carlton Gibson from the previously mentioned talk:
@ -261,7 +267,9 @@ So this is what I'm doing.
3. Gather community interest - ongoing
4. Merge!
My best case scenario would be to land it in Django 5.1, but then I'm close to daydreaming.
I want to emphasize that my goal is not the get the exact feature set of `django-view-decorator` into Django core. My goal is to use `django-view-decorator` as a, preferably stable, place to try out different approaches and evaluate which ideas are good and which are not.
One thing I have not touched upon in this blog post, is the different arguments which the decorator can take to replace decorators such as `@login_required` and `@permission_required`. That is simply because I'm not sure if the decorator should take on that responsibility. So everything is up in the air and my goal, besides ultimately getting this pattern into Django, is to figure out how this pattern benefits Django the most.
No matter whether my plan to get this pattern, in some form or another, into Django will succeed, I will continue to maintain `django-view-decorator` as an alternative to the current `views.py/urls.py` approach.