I have multiple tools in my app (about 20). Each can be accessed with an object already selected, or without connection to an object. Currently I am utilizing this like:
urlpatterns = [
path('tool_one/', views.ToolOneView.as_view(), name='tool-one'),
path('<int:id>/tool_one/', views.ToolOneView.as_view(), name='tool-one'),
# [... 18 more paths ...]
path('tool_twenty/', views.ToolTwentyView.as_view(), name='tool-twenty'),
path('<int:id>/tool_twenty/', views.ToolTwentyView.as_view(), name='tool-twenty')
]
Now I can link to my tool in two ways:
<a href="{% url 'tools:tool-one' id=object.id %}">
Option A: Tool one with object attached
</a>
<!--or-->
<a href="{% url 'tools:tool-one' %}">
Option B: Tool one without object attached
</a>
It would be much easier for me if I could always just use option A but allowing that value for object.id
to be None
. In the case of object.id = None
it should direct the user the the view without the object attached.
With my current approach I dislike the repetitiveness in the urlpatterns
and also within the templates.
Example: I have a navigation bar linking to all the tools without an object attached. On the DetailView
of my Object
I have linking to all the tools with the object attached. It is basically the same snippet that in theory I could reuse but apparently can't because with the latter I have to add id=object.id %}
This should be easy to do since the usecase probably occurs very often, so please enlighten me!
Use id=0 for no object. Then you don't need two sets of URLS. Just code that doesn't attempt to get an object if kwarg id=0. I'm assuming that id is a Django default primary key. These are always positive integers.
If your CBV is using the SingleObjectMixin get_object method to fetch the object, you can subclass it to handle zero:
def get_object(self):
if self.kwargs['id'] == '0':
self.object = None
return
return super().get_object()
Depending on the similarity or not of the views tool_one to tool_twenty you might also use a single URL and view
path('<int:id>/<str:tool_id>/', views.ToolAny.as_view(), name='tool-any'),
check that kwarg tool_id is valid early in the view, returning Http404 if not. Further in, use it to dispatch to the correct processing.