Skip to main content
 首页 » 编程设计

python之Django 模型与用户模型的关系

2025年04月02日35jillzhang

我是论坛的新手,遇到了问题。

在 Django 中,我试图通过 OnetoOneField 将其引用到用户对象来创建一个 UserProfile 类。当我尝试迁移时,我得到:

“您正试图在没有默认值的情况下向作者添加不可为空的字段‘id’;我们不能这样做(数据库需要一些东西来填充现有行)。 请选择修复: 1) 现在提供一次性默认值(将在所有现有行上设置) 2) 退出,让我在 models.py 中添加一个默认值"

据我了解,用户模型中的某些字段(例如“id”)不允许为空。

当我尝试设置默认值时,它会进行迁移,但迁移失败并出现语法错误。

我的问题是如何在不编写自定义 User 类的情况下允许 Null,或设置一个有效的默认值,这是否可能?

我真的很感激任何帮助。

这是我的代码:

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) 

编辑:

如果我尝试设置默认值并尝试迁移,就会发生这种情况:

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 

编辑: 好像我通过创建一个新项目并逐步复制模型和迁移来解决它。仍然想知道那里发生了什么,因为我刷新了数据库并多次删除了迁移文件,但它仍然抛出错误。

感谢您的帮助!

请您参考如下方法:

看看这个:

https://docs.djangoproject.com/es/1.9/topics/db/examples/one_to_one/

您的代码与用户是一对一的。当您设置它时,它意味着 CASCADE 删除,因此永远不能为 null。

如果您更改为一对多,并且只需确保您只为外键插入一个对象,它就会起作用。否则,请更改级联规则。

但是,我要说的是,这不是一个好主意,因为如果将其设为空,它与其他记录的区别是什么。考虑第二个 PK 字段。

祝你好运。