I have an app with 2 models and I’m trying to create a List View and a Detail View. The list view worked fine, but when I created the detail view the list view stopped working and it’s prompting me with this error: “Field ‘id’ expected a number but got ‘list’.
Models.py
from django.db import models # Create your models here. class schools(models.Model): name=models.CharField(max_length=256) principal=models.CharField(max_length=256) def __str__(self): return self.name class students(models.Model): name=models.CharField(max_length=256) age=models.PositiveIntegerField() school=models.ForeignKey(schools,related_name='students',on_delete=models.CASCADE)
views.py
from django.shortcuts import render from django.views.generic import DetailView,ListView,CreateView,FormView,UpdateView from basicapp import models,forms from django.http import HttpResponseRedirect, HttpResponse # Create your views here. class SchoolListView(ListView): model = models.schools class SchoolDetailView(DetailView): context_object_name='schools_detail' model=models.schools template_name='basicapp/schools_detail.html'
urls.py
from django.contrib import admin from django.urls import path,re_path from basicapp import views urlpatterns=[ re_path(r'^(?P<pk>[-w]+)/$',views.SchoolDetailView.as_view(),name="detail"), path('list',views.SchoolListView.as_view(),name="list"), path('create',views.cview.as_view(),name="create"), path('index',views.index,name='index'), ]
and my templates:
{% extends 'basicapp/base.html' %} {% block body_block %} <h1>Welcome to the List of Schools Page!</h1> <ol> {% for school in schools_list %} <h2> <li><a href="{{school.id}}"></a>{{school.name}}</li> </h2> {% endfor %} </ol> {% endblock %}
{% extends 'basicapp/base.html' %} {% block body_block %} <div class="jumbotron"> <h1>School Detail Page</h1> <h2>School Details:</h2> <p>{{ schools_detail.name }}</p> <p>{{ schools_detail.principal }}</p> <h3>Students:</h3> {% for student in school_detail.students.all %} <p>{{ student.name }} who is {{ student.age }} years old.</p> {% endfor %} </div> {% endblock %}
Advertisement
Answer
Your pattern ^(?P<pk>[-w]+)/$
matches list
hence the view SchoolDetailView
gets used for that url (in fact also for the other urls after it), hence you need to make the pattern more specific. For instance the pk is going to be an integer only so you can match that instead:
re_path(r'^(?P<pk>d+)/$', views.SchoolDetailView.as_view(), name="detail"),
Better yet this doesn’t need you to use re_path
does it? the default int
path converter handles it quite well:
path('<int:pk>/', views.SchoolDetailView.as_view(), name="detail"),
Note: Class names should ideally be in
PascalCase
and also model names should be singular so instead ofa better name for the model would beschools
School
, instead ofit would bestudents
Student
. See PEP 8 — Style Guide for Python Code