Positional Arguments withDjango url patterns

1.6k views Asked by At

I have been stuck on this Django error for a while:

tutorials() missing 1 required positional argument: 'tutorial_id'

Below are the files. Using Python 3.5 and Django 1.10.

tutorials/urls.py:

from django.conf.urls import url
from . import views

app_name = 'tutorials'

urlpatterns = [
    url(r'^(?P<tutorial_id>[0-9]+)/$', views.tutorials, name='tutorials'),
    url(r'^$', views.tutorials, name='tutorials'),
]

tutorials/views.py

from django.shortcuts import render, get_object_or_404
from .models import Tutorial, Lesson

def tutorials(request, tutorial_id):
    tutorials = get_object_or_404(Tutorial, pk=tutorial_id)
    return render(request, 'tutorials/tutorials.html', { 'tutorials': tutorials})

When I visit website.com/tutorials I get the error but it will work fine if I go to website.com/tutorials/1 which is good. But I want to be able to access /tutorials so I can ad information to this link.

3

There are 3 answers

1
Chikiro On BEST ANSWER

Perhaps you need different functions to serve a collection of tutorials and a single tutorial.

tutorials/urls.py

from django.conf.urls import url
from . import views

app_name = 'tutorials'

urlpatterns = [
    url(r'^(?P<tutorial_id>[0-9]+)/$', views.tutorial_view, name='tutorials'),
    url(r'^$', views.tutorials_view, name='tutorials'),
]

tutorials/views.py

from django.shortcuts import render, get_object_or_404
from .models import Tutorial, Lesson

def tutorials_view(request):
    tutorials = Tutorial.objects.all()
    return render(request, 'tutorials/tutorials.html', { 'tutorials': tutorials})

def tutorial_view(request, tutorial_id):
    tutorial = get_object_or_404(Tutorial, pk=tutorial_id)
    return render(request, 'tutorials/tutorial.html', { 'tutorial': tutorial})

Your need to create a separate template for a single tutorial view.

0
vodopyanovas On

You need to pass this argument via url (1) in your template or make a default value for it in views.py (2).

  1. {% url 'tutorials' template.id %}
  2. def tutorials(request, tutorial_id=1):
1
Renjith Thankachan On

It is because of django url pattern ordering, just change the order since, regular expression ^(?P<tutorial_id>[0-9]+)/ is matched. Options are :

change the code to

# tutorials_list is different view to handle list
urlpatterns = [
    url(r'^$', views.tutorials_list, name='tutorials-list'),
    url(r'^(?P<tutorial_id>[0-9]+)/$', views.tutorials, name='tutorials-detail'),
]

or check this in view,

def tutorials(request, *args, **kwargs):
    tutorial_id = kwargs.get('tutorial_id', None)
    tutorials = get_object_or_404(Tutorial, pk=tutorial_id)
    return render(request, 'tutorials/tutorials.html', { 'tutorials': tutorials})

with one URL defined int url_patterns

urlpatterns = [
    url(r'^(?P<tutorial_id>[0-9]+)/$', views.tutorials, name='tutorials-detail'),
]