Search code examples
djangodatabasedjango-modelssqlitedumpdata

How to properly extend django user model and seed databse


I created a model that extends on Django's user model. I am now trying to seed the database with this type of user, but I get an error when trying to use the loaddata call.

I extended the user model, creating a different user type called FocalUser. I created a user.json file with the information. When I got the error the first time, I then double checked this by using dumpdata. The information didn't seem to be correct, or as I imagined it from the dump.

This is from the models.py file where I create FocalUser:

class FocalUser(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    userID = CharField(max_length=50)
    type_id = CharField(max_length=50)
    is_active = BooleanField()

This is my users.json file:

[
  {
    "model": "focal_login.FocalUser",
    "pk": 1,
    "fields": {
      "username": "[email protected]",
      "email": "[email protected]",
      "password": "password",
      "first_name": "Kate",
      "last_name": "Catalena",
      "userID": 2,
      "type_id": 2,
      "is_active": "True" 
    }
  }

]

The error resulting from python3 manage.py loaddata users.json:

Traceback (most recent call last):
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/db/models/options.py", line 564, in get_field
    return self.fields_map[field_name]
KeyError: 'last_name'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/serializers/json.py", line 69, in Deserializer
    yield from PythonDeserializer(objects, **options)
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/serializers/python.py", line 116, in Deserializer
    field = Model._meta.get_field(field_name)
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/db/models/options.py", line 566, in get_field
    raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
django.core.exceptions.FieldDoesNotExist: FocalUser has no field named 'last_name'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/management/base.py", line 316, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/management/base.py", line 353, in execute
    output = self.handle(*args, **options)
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/management/commands/loaddata.py", line 72, in handle
    self.loaddata(fixture_labels)
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/management/commands/loaddata.py", line 113, in loaddata
    self.load_label(fixture_label)
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/management/commands/loaddata.py", line 168, in load_label
    for obj in objects:
  File "/Users/kate/.local/share/virtualenvs/login-E6JpMIQ_/lib/python3.5/site-packages/django/core/serializers/json.py", line 73, in Deserializer
    raise DeserializationError() from exc
django.core.serializers.base.DeserializationError: Problem installing fixture '/Users/kate/Desktop/login/users.json': 

The dumpdata looks like"

[{"model": "contenttypes.contenttype", "pk": 1, "fields": {"app_label": "admin", "model": "logentry"}}, {"model": "contenttypes.contenttype", "pk": 2, "fields": {"app_label": "auth", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 3, "fields": {"app_label": "auth", "model": "user"}}, {"model": "contenttypes.contenttype", "pk": 4, "fields": {"app_label": "auth", "model": "group"}}, {"model": "contenttypes.contenttype", "pk": 5, "fields": {"app_label": "contenttypes", "model": "contenttype"}}, {"model": "contenttypes.contenttype", "pk": 6, "fields": {"app_label": "sessions", "model": "session"}}, {"model": "contenttypes.contenttype", "pk": 7, "fields": {"app_label": "focal_login", "model": "focaluser"}}, {"model": "contenttypes.contenttype", "pk": 8, "fields": {"app_label": "focal_login", "model": "event"}}, {"model": "contenttypes.contenttype", "pk": 9, "fields": {"app_label": "focal_login", "model": "project"}}

Did I not properly extend the user model to create FocalUser? The user model has fields: username, email, password, first_name, and last_name. So why when I try to seed is an error say KeyError: 'last_name'


Solution

  • You have just done the OneToOne relationship between default Django User model and your model to support additional fields.

    If this suits you, you should change your users.json to something similar to following ( easier to create User and FocalUser objects in db then dump them out to be sure about structure):

    [
      {
        "model": "auth.user",
        "pk": 1,
        "fields": {
          "username": "[email protected]",
          "email": "[email protected]",
          "password": "password",
          "first_name": "Kate",
          "last_name": "Catalena",
           standard user fields
           ...
        }
      }
      {
        "model": "focal_login.FocalUser",
        "pk": 1,
        "fields": {
          "user": 1,
          "userID": 2,
          "type_id": 2,
          "is_active": "True" 
        }
      }
    
    ]
    

    But what I suspect you would rather replace default Django user model if that is case there is substituting user documentation