[Field 'id' expected a number but got ''] error while running test server

Hi,

I’m building my first web app with Django. It’s destined to display a catalog of relatively short monographies, called notices, of antique architecture objects.

There’s an list view that shows the clickable title of the 40 lasts recorded notices, and a detail view to display the notice itself: title, record date, link to pictures, etc.

While certain notices display as expected, I’ve got an error that I can’t figure out when I click on certain others. I checked in the database but didn’t find the answer yet.

Here is my urls.py so far:

from django.urls import path, include
from . import views
from notices.models import ObjetArchi

app_name = 'notices'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>', views.DetailView.as_view(), name='detail'),
]

and my views.py:

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from notices.models import ObjetArchi

class IndexView(generic.ListView):
    template_name = 'notices/index.html'
    context_object_name = 'dernier_oa_liste'

    def get_queryset(self):
        return ObjetArchi.objects.order_by('-date')[:40]

class DetailView(generic.DetailView):
    model = ObjetArchi
    template_name = 'notices/detail.html'

My 3 HTML templates:

base.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      OrAG{% block title %}{% endblock %}
    </title>
  </head>
  <body>
    <header>
      {% block headerContent %}{% endblock %}
    </header>
    <section id="content">
      {% block content %}{% endblock %}
    </section>
  </body>
</html>

index.html:

{% extends "notices/base.html" %}

{% block title %} - Accueil{% endblock %}

{% block content %}

  {% block bodyId %}Dernières notices saisies :{% endblock %}

  {% if dernier_oa_liste %}
      <ul>
      {% for objetarchi in dernier_oa_liste %}
          <li><a href="{% url 'notices:detail' objetarchi.id %}">{{ objetarchi.titre }}</a></li>
      {% endfor %}
      </ul>
  {% else %}
      <p>Aucune notice n'est accessible.</p>
  {% endif %}

{% endblock %}

and detail.html:

{% extends "notices/base.html" %}
{% block title %} - Notices{% endblock %}

{% comment %} {% block bodyId %}notices{% endblock %}
{% block headerContent %}Ornementation architecturale des Gaules {% endblock %}  {% endcomment %}

{% block content %}
<h1>{{ object.titre }}</h1>
  <p><i>Notice n°{{ object.reference }}, publiée le {{ object.date }}.</i></p>
  <p>{{ object.resume }}</p>
{% comment %} (more content here) {% endcomment %}
{% endblock %}

And finally here is the error that shows up when trying to show some notices (not all):

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/notices/101

Django Version: 3.1.4
Python Version: 3.8.6
Installed Applications:
['notices.apps.NoticesConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template /home/jeremy/amubox/code/orag/notices/templates/notices/base.html, error at line 0
   Field 'id' expected a number but got ''.
   1 : <!DOCTYPE html>
   2 : <html>
   3 :   <head>
   4 :     <meta charset="utf-8">
   5 :     <title>
   6 :       OrAG{% block title %}{% endblock %}
   7 :     </title>
   8 :   </head>
   9 :   <body>
   10 :     <header>


Traceback (most recent call last):
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 829, in _resolve_lookup
    current = current[bit]

During handling of the above exception ('ObjetArchi' object is not subscriptable), another exception occurred:
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 173, in __get__
    rel_obj = self.field.get_cached_value(instance)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/fields/mixins.py", line 15, in get_cached_value
    return instance._state.fields_cache[cache_name]

During handling of the above exception ('provinceantique'), another exception occurred:
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/fields/__init__.py", line 1774, in get_prep_value
    return int(value)

The above exception (invalid literal for int() with base 10: '') was the direct cause of the following exception:
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/core/handlers/base.py", line 202, in _get_response
    response = response.render()
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/response.py", line 83, in rendered_content
    return template.render(context, self._request)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 988, in render
    output = self.filter_expression.resolve(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 671, in resolve
    obj = self.var.resolve(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 796, in resolve
    value = self._resolve_lookup(context)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/template/base.py", line 837, in _resolve_lookup
    current = getattr(current, bit)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 187, in __get__
    rel_obj = self.get_object(instance)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 154, in get_object
    return qs.get(self.field.get_reverse_related_filter(instance))
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/query.py", line 418, in get
    clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/query.py", line 942, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/query.py", line 962, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, *args, **kwargs)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/query.py", line 969, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1358, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1377, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1237, in build_filter
    return self._add_q(
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1377, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1319, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1165, in build_lookup
    lookup = lookup_class(lhs, rhs)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/lookups.py", line 24, in __init__
    self.rhs = self.get_prep_lookup()
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/lookups.py", line 76, in get_prep_lookup
    return self.lhs.output_field.get_prep_value(self.rhs)
  File "/home/jeremy/.local/lib/python3.8/site-packages/django/db/models/fields/__init__.py", line 1776, in get_prep_value
    raise e.__class__(

Exception Type: ValueError at /notices/101
Exception Value: Field 'id' expected a number but got ''.

Any help would be very much appreciated!

I can post extracts of the database if needed to compare data.

Thanks a lot!

Thank you for providing all this information! it’s a great help. I think we may also need to see the ObjetArchi model as being the final piece of the puzzle.

Here it is!

class ObjetArchi(models.Model):
    id = models.PositiveSmallIntegerField(
        primary_key=True,
        db_column='codeOA'
        )
    reference = models.PositiveSmallIntegerField(
        db_column='refOA'
        )
    version = models.PositiveSmallIntegerField(
        db_column='versionOA',
        verbose_name='Version'
        )
    memo_modif = models.CharField(
        max_length=200,
        verbose_name='Mémo Modif.',
        blank=True,
        db_column='memoModif'
        )
    date = models.DateField(
        default=timezone.now,
        db_column='dateOA',
        verbose_name='Date de publication de la notice'
        )
    lien_pdf = models.CharField(
        max_length=100,
        verbose_name='Lien PDF',
        blank=True,
        db_column='lienPDFOA'
        )
    observations = models.PositiveSmallIntegerField(
        db_column='observOA'
        )
    ref_repro = models.CharField(
        max_length=10,
        db_column='RefReprOA'
        )
    lieu_dit = models.CharField(
        max_length=100,
        verbose_name='Lieu-dit',
        blank=True,
        db_column='lieuOA'
        )
    titre = models.CharField(
        max_length=100,
        verbose_name='Titre de la notice',
        blank=True,
        db_column='titreOA'
        )
    x = models.DecimalField(
        max_digits=8,
        decimal_places=6,
        verbose_name='Longitude',
        blank=True,
        null=True,
        db_column='longitudeOA'
        )
    y = models.DecimalField(
        max_digits=8,
        decimal_places=6,
        verbose_name='Latitude',
        blank=True,
        null=True,
        db_column='latitudeOA'
        )
    contexte = models.CharField(
        max_length=500,
        verbose_name='Contexte Archéologique',
        blank=True,
        db_column='contexteOA'
        )
    attribution = models.CharField(
        max_length=500,
        verbose_name='Attribution',
        blank=True,
        db_column='AttributionOA'
        )
    cons_no_inv = models.CharField(
        max_length=50,
        verbose_name='Numéro d\'inventaire',
        blank=True,
        db_column='InventaireConsOA'
        )
    cons_lieu = models.CharField(
        max_length=100,
        verbose_name='Lieu de conservation',
        blank=True,
        db_column='LieuConsOA'
        )
    cons_loc = models.CharField(
        max_length=100,
        verbose_name='Localisation précise',
        blank=True,
        db_column='locConsOA'
        )
    description = models.CharField(
        max_length=2000,
        verbose_name='Description',
        blank=True,
        db_column='DescriptionAO'
        )
    inedit = models.BooleanField(
        verbose_name='Inédit',
        db_column='biblioInedit'
        )
    ref_biblio = models.CharField(
        max_length=500,
        verbose_name='Références bibliographiques',
        blank=True,
        db_column='RefBiblioOA'
        )
    analyse = models.CharField(
        max_length=2000,
        verbose_name='Analyse',
        blank=True,
        db_column='AnalyseOA'
        )
    date_chrono_debut = models.DateField(
        verbose_name='Date de début de la fenêtre temporelle',
        db_column='dateChronoDebut'
        )
    date_chrono_fin = models.DateField(
        verbose_name='Date de fin de la fenêtre temporelle',
        db_column='dateChronoFin'
        )
    polychromie = models.BooleanField(
        verbose_name='Polychromie',
        db_column='polyMateriaux'
        )
    observations_comp = models.CharField(
        max_length=2000,
            verbose_name='Observations géologiques et techniques complémentaires',
        blank=True,
        db_column='memoMateriaux'
        )
    hauteur_debut = models.IntegerField(
        verbose_name='Hauteur totale de l\'objet analysé de la présente notice',
        db_column='HauteurDebutOA',
        null=True
        )
    hauteur_fin = models.IntegerField(
        verbose_name='Hauteur (2)',
        db_column='HauteurFinOA',
        blank=True,
        null=True
    )
    support = models.BooleanField(
          verbose_name='Il s\'agit d\'un support (ou d\'une de ses composantes)',
          db_column='pilier'
          )
    materiau = models.ForeignKey(
        'Materiau',
        on_delete=models.CASCADE,
        related_name='objetarchi',
        blank=True,
        db_column='Materiaux_codeMateriau'
        )
    ensemble = models.ForeignKey(
        'Ensemble',
        on_delete=models.CASCADE,
        related_name='objetarchi',
        blank=True,
        db_column='EA_codeEA'
        )
    citeantique = models.ForeignKey(
        'CiteAntique',
        on_delete=models.CASCADE,
        related_name='objetarchi',
        blank=True,
        db_column='CiteAntiques_codeCiteAntique'
        )
    provinceantique = models.ForeignKey(
        'ProvinceAntique',
        on_delete=models.CASCADE,
        related_name='objetarchi',
        blank=True,
        db_column='ProvinceAntiques_codeProvinceAntique'
        )
    siteantique = models.ForeignKey(
        'SiteAntique',
        on_delete=models.CASCADE,
        related_name='objetarchi',
        blank=True,
        db_column='SiteAntiques_codeSiteAntique'
        )
    users = models.ForeignKey(
        'Users',
        on_delete=models.CASCADE,
        related_name='objetarchi',
        blank=True,
        db_column='Users_codeUser'
        )
    cons_depot = models.ForeignKey(
        'DepotConservation',
        on_delete=models.CASCADE,
        related_name='objetarchi',
        blank=True,
        verbose_name='Dépôt de conservation',
        db_column='DepotConservation_codeDepotCons'
        )
    monument = models.ForeignKey(
        'Monument',
        on_delete=models.CASCADE,
        related_name='objetarchi',
        blank=True,
        db_column='Monument_codeMonument'
        )
    flag_del_objetarchi = models.BooleanField(
        verbose_name='Supprimer l\'objet architectural',
        db_column='flagDeleteOA'
        )
    prov_pays = models.ForeignKey(
        'Pays',
        on_delete=models.CASCADE,
        related_name='objetarchi_prov',
        blank=True,
        db_column='prov_codePays'
        )
    prov_region = models.ForeignKey(
        'Region',
        on_delete=models.CASCADE,
        related_name='objetarchi_prov',
        blank=True,
        db_column='prov_codeRegionAdmin1'
        )
    prov_departement = models.ForeignKey(
        'Departement',
        on_delete=models.CASCADE,
        related_name='objetarchi_prov',
        blank=True,
        db_column='prov_codeRegionAdmin2'
        )
    prov_ville = models.ForeignKey(
        'Ville',
        on_delete=models.CASCADE,
        related_name='objetarchi_prov',
        blank=True,
        db_column='prov_codeVilles'
        )
    cons_pays = models.ForeignKey(
        'Pays',
        on_delete=models.CASCADE,
        related_name='objetarchi_cons',
        blank=True,
        db_column='cons_codePays'
        )
    cons_region = models.ForeignKey(
        'Region',
        on_delete=models.CASCADE,
        related_name='objetarchi_cons',
        blank=True,
        db_column='cons_codeRegionAdmin1'
        )
    cons_departement = models.ForeignKey(
        'Departement',
        on_delete=models.CASCADE,
        related_name='objetarchi_cons',
        blank=True,
        db_column='cons_codeRegionAdmin2'
        )
    cons_ville = models.ForeignKey(
        'Ville',
        on_delete=models.CASCADE,
        related_name='objetarchi_cons',
        blank=True,
        db_column='cons_codeVilles'
        )
    class PertinenceOAChoix(models.IntegerChoices):
        A = 10
        B = 9
        C = 8
        D = 7
        E = 6
        F = 5
        G = 4
        H = 3
        I = 2
        J = 1
    pertinence = models.IntegerField(
        choices=PertinenceOAChoix.choices,
        verbose_name='Pertinence de la datation. A: très pertinent, J: non pertinent.',
        db_column='pertinenceDatation'
        )
    stuc = models.BooleanField (
        verbose_name='Stuc',
        db_column='stucFlag'
        )
    hauteur_restituee = models.BooleanField (
        verbose_name='Hauteur restituée',
        db_column='hauteurRestitueeFlag'
        )
    resume = models.CharField(
        max_length=2000,
        verbose_name='Résumé',
        blank=True,
        db_column='resumeInternetOA'
        )
    issn_objetarchi = models.IntegerField(
        db_column='IssnOA'
    )
    flag_soumission_comite = models.BooleanField (
        verbose_name='Soumettre la notice au comité de lecture',
        db_column='flagSoumissionComite'
        )

    class Meta:
        managed = False
        db_table = 'OA'

    def __str__(self):
        return self.titre

Hi JeremyG,

It looks like your django model does not control the database schema of ObjetArchi ( determined by seeing managed = False). Because of that, the field definitions on the model may differ than what the database schema is. Is it possible that OA table’s id column is a string based column?

Edit:

I incorrectly thought that the error was in the url routing. It’s in the models. I revised a large part of my answer.

1 Like

Hi CodenameTim,

Thanks for looking into it.

I suspected something like that but the id column (codeOA) is a smallint type, so not string based if I understand correctly.

Can you query the table looking for null values?

Is the actual codeOA column a MySQL smallint or is it a smallint unsigned? Can you verify that there are no negative values in that column? (Also verify the actual type within the schema?)

I’m working on a sample db with 99 individuals, so a visual check is easy, there are no null values unfortunately.

It’s a smallint type with no negative values.

This appears to be an app-based urls.py file. What does your base urls.py file look like?

Additionally, it’d be helpful to isolate the actual queryset that’s causing this issue. One way would be to use a debugger to inspect the context when the exception gets raised. Another is to comment out parts of the detail view and template until it renders properly for /notices/101. Once it does, we know generally which part fails and hopefully be able to see the true issue more clearly.

1 Like

Ken,

I actually pasted my whole urls.py here. I’m just starting with Django and still kind of following the tutorial to help me, so there probably are a lot of mistakes in the files… Thanks for your understanding! :slight_smile:

Nope, that’s fine. Knowing that that’s the only urls.py file eliminates another possible cause of the error.

I agree with @CodenameTim here - it might be time to do some divide & conquer. If you go directly to /notices/101 and it works, then I’d go back and look at the rendered url from the listing page to verify that all the links were rendered properly.
Otherwise, I’d start simplifying the template to see what’s causing the issue. I might also take a very close look at two rows - one that works and one that doesn’t, comparing the individual fields of each.

1 Like