Search code examples
pythondjangomodels

Django Models Relations to User Model


I'm new to the forum and I've got a problem.

in Django im trying to create a UserProfile class by referencing it via a OnetoOneField to an User Object. When i try to migrate, I get:

"You are trying to add a non-nullable field 'id' to author without a default; we can't do that (the database needs something to populate existing rows). Please select a fix: 1) Provide a one-off default now (will be set on all existing rows) 2) Quit, and let me add a default in models.py"

I understand, that there are some fields in the User model (for example "id") that are not allowed to be null.

When I try to set a default it will makemigrations, but migrate fails with a syntax error.

My Question is how do I allow Null, or set a default that works, without writing a custom User class, and is that even possible ?

I'd really appreciate any help with this.

Here is my Code:

from django.db import models
from django.contrib.auth.models import User as User_django

class User(User_django):
    pass

class Author(models.Model):
    user = models.OneToOneField(User, null=True)

class BaseElement(models.Model):

    author=models.ForeignKey(Author, null=True)
    upvotes = models.PositiveIntegerField(default=0)
    downvotes = models.PositiveIntegerField(default=0)
    created = models.DateTimeField(auto_now_add=True, null=True)

    def vote_up(self):
        self.upvotes.value = self.upvotes.value + 1

    def vote_down(self):
        self.downvotes.value = self.downvotes.value + 1

    class Meta:
        abstract = True


class Post(BaseElement):
    content = models.TextField(max_length=240)
    tags = models.CharField(max_length=40, blank=True)
    said_by = models.CharField(max_length=40)
    said_at = models.CharField(max_length=40, blank=True)

    def get_comments(self):
        return self.comment_set.all()

    def get_comments_anzahl(self):
        return self.comment_set.all().count()


class Comment(BaseElement):
    content = models.TextField(max_length=140)
    commented_post = models.ForeignKey(Post, related_query_name="comment", null=True)

EDIT:

This happens if I try to set a default and try to migrate:

You are trying to add a non-nullable field 'id' to author without a  
default; we can't do that (the database needs something to populate 
existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can  
do e.g. timezone.now()
>>> 1
 Migrations for 'post':
 0003_auto_20160505_1237.py:
  - Change Meta options on author
  - Change managers on author
  - Remove field user_ptr from author
  - Add field id to author
  - Add field user to author

 Operations to perform:
 Apply all migrations: contenttypes, admin, sessions, post, auth
 Running migrations:
   Rendering model states... DONE
   Applying post.0003_auto_20160505_1237...Traceback (most recent call last):
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
   return self.cursor.execute(sql, params)
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 323, in execute
   return Database.Cursor.execute(self, query, params)
   sqlite3.OperationalError: near ")": syntax error

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

 Traceback (most recent call last):
    File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django  /core/management/__init__.py", line 353, in execute_from_command_line
   utility.execute()
  File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/core/management/__init__.py", line 345, in execute
   self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/core/management/base.py", line 348, in run_from_argv
   self.execute(*args, **cmd_options)
  File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/core/management/base.py", line 399, in execute
    output = self.handle(*args, **options)
  File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/core/management/commands/migrate.py", line 200, in handle
   executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
  File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/migrations/executor.py", line 92, in migrate
    self._migrate_all_forwards(plan, full_plan, fake=fake,  fake_initial=fake_initial)
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/migrations/executor.py", line 121, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/migrations/executor.py", line 198, in apply_migration
   state = migration.apply(state, schema_editor)
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/migrations/migration.py", line 123, in apply
   operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/migrations/operations/fields.py", line 121, in database_forwards
   schema_editor.remove_field(from_model, from_model._meta.get_field(self.name))
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/sqlite3/schema.py", line 247, in remove_field
    self._remake_table(model, delete_fields=[field])
    File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/sqlite3/schema.py", line 197, in _remake_table
    self.quote_name(model._meta.db_table),
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 110, in execute
    cursor.execute(sql, params)
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute
     return super(CursorDebugWrapper, self).execute(sql, params)
    File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
    File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/utils.py", line 95, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
   return self.cursor.execute(sql, params)
   File "/home/jaidmin/.conda/envs/cyf/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 323, in execute
    return Database.Cursor.execute(self, query, params)
   django.db.utils.OperationalError: near ")": syntax error

EDIT: It seems like I solved it by creating a new project and step by step copying the models and migrating. Still wondering what was going on there, because I flushed the database and deleted the migration files multiple times and it was still throwing errors.

Thanks for the help !


Solution

  • Just import django's built-in User model like this:

    from django.contrib.auth.models import User
    

    and delete this line:

    class User(User_django):
        pass
    

    from your code as it is completely unnecessary.

    UPDATE: Also it looks like your problem has nothing to do with the User model. I think somehow you added an id field to your Author model and deleted it (maybe after an unsuccessful migration). If this is the case, then you could edit your 0003_auto_20160505_1237.py. To do that open it and remove the lines which look something like this:

    migrations.AddField(
        model_name='author',
        name='id',
        field=models.someFieldType(options)),
    ),
    

    and try again.