Skip to content
Advertisement

Django Error: Field ‘id’ expected a number but got ‘list’

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 of schools a better name for the model would be School, instead of students it would be Student. See PEP 8 — Style Guide for Python Code

Advertisement