Models -Type errors, and Primary keys

Hello, I’m new to Django, and models.

Is there any reason why a Model would throw an error without using a custom primary key(primary_key=True)

Without using the custom primary key, in any module I create, I get the error below.

Type Error: Field ‘id’ expected a number but got ‘author’
Type Error: Field ‘id’ expected a number but got ‘name’

my code:

from django.db import models

class Plan(models.Model):
author = models.CharField(max_length=64)
the_plan = models.CharField(max_length=64)

def __str__(self):
    return f"{self.author}"

class Weapon(models.Model):
name = models.CharField(max_length=64)
type = models.CharField(max_length=64)

def __str__(self):
    return f"{self.name}"

Thanks for any help!

All Django models have a primary key. See Model field reference | Django documentation | Django and Models | Django documentation | Django.

1 Like

I’m new to Django as well but have succesfully used models that did not have a custom primary key. In these situations Django creates an id pk automatically. When are you receiving these errors?

1 Like

I had a few practice projects with several baseline apps installed. Each had a few models created, all without a custom primary key. Everything was working, I went back in a day later, and I could not save the models in the ORM.

I kept getting this error below:

Type Error: Field ‘id’ expected a number but got ‘first_name’

Adding a custom primary key to each model stopped the errors, and I was able to save the model and make migrations. Without the custom, primary key things would break, and the Type Error returned.

I created some new projects, and models without the custom key, and all function properly.
I’m not sure what happened. Maybe the python cache files were causing a conflict?

Anyways, it was all just dummy data, but a strange event nonetheless in this learning process.

It would be of more help to us if you posted the complete traceback of the error, along with the code throwing it.

This simple model is an example

from django.db import models

# Create your models here.

class Bonsai(models.Model):
    
    # remove (s) from table name in Django admin
    class Meta:
        verbose_name_plural = "Bonsai"    

    name = models.CharField(max_length=64)
    age = models.IntegerField()
    placement = models.CharField(max_length=64)

    def __str__(self):
        return f"{self.name} ({self.age} years)"

o = Bonsai(“Oak”, 44,“Outdoor”)
o.save()

Traceback…

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\base.py", line 812, in save
    self.save_base(
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\base.py", line 863, in save_base
    updated = self._save_table(
              ^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\base.py", line 976, in _save_table
    updated = self._do_update(
              ^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\base.py", line 1019, in _do_update
    filtered = base_qs.filter(pk=pk_val)
               ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\query.py", line 1420, in filter
    return self._filter_or_exclude(False, args, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\query.py", line 1438, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\query.py", line 1445, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\sql\query.py", line 1532, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\sql\query.py", line 1562, in _add_q
    child_clause, needed_inner = self.build_filter(
                                 ^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\sql\query.py", line 1478, in build_filter
    condition = self.build_lookup(lookups, col, value)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\sql\query.py", line 1303, in build_lookup
    lookup = lookup_class(lhs, rhs)
             ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\lookups.py", line 27, in __init__
    self.rhs = self.get_prep_lookup()
               ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\lookups.py", line 341, in get_prep_lookup
    return super().get_prep_lookup()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\lookups.py", line 85, in get_prep_lookup
    return self.lhs.output_field.get_prep_value(self.rhs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Studio\Desktop\CodeMedia\env\Lib\site-packages\django\db\models\fields\__init__.py", line 2020, in get_prep_value
    raise e.__class__(
ValueError: Field 'id' expected a number but got 'Oak'.

One issue is that you’re not using the model correctly.

From the docs at Making queries | Django documentation | Django

To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database.

It’s not considered “proper” to try to create the instance using positional arguments.

I don’t have an explanation as to why it works in some cases - I’d just chalk that up as being “one of those things”.

That solved it.

Thanks for the solution Ken!

Also, thanks for the suggestions @Artur!