Django:带有用户的模型 OneToOneField 无法添加默认值
Django: model OneToOneField with User can't add default value
我有一个模型,我想添加一个 OneToOneField 来保存对象的创建者:
models.py
creator = models.OneToOneField(User, blank=True,
default=User.objects.filter(
username="antoni4040"))
我已经有一个包含项目的数据库,只希望默认值为管理员用户,该用户的用户名为 "antoni4040"。当我尝试在没有默认字段的情况下进行迁移时,它会要求提供默认值,所以我无法摆脱它。但这是 运行 makemigrations 时我得到的:
Migrations for 'jokes_app':
0008_joke_creator.py:
- Add field creator to joke
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 150, in handle
self.write_migration_files(changes)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 178, in write_migration_files
migration_string = writer.as_string()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 167, in as_string
operation_string, operation_imports = OperationWriter(operation).serialize()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 124, in serialize
_write(arg_name, arg_value)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 88, in _write
arg_string, arg_imports = MigrationWriter.serialize(_arg_value)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 433, in serialize
return cls.serialize_deconstructed(path, args, kwargs)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 318, in serialize_deconstructed
arg_string, arg_imports = cls.serialize(arg)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 517, in serialize
item_string, item_imports = cls.serialize(item)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 540, in serialize
"topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: <User: antoni4040>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/1.9/topics/migrations/#migration-serializing
我做错了什么?
您正在使用查询集User.objects.filter(username="antoni4040")
。要获取模型实例,您可以使用 User.objects.get(username="antoni4040")
.
但是,您不应将模型实例用作模型字段中的默认值。如果用户不存在于数据库中,则没有错误处理。事实上,如果 models.py
在 运行 初始迁移之前加载,那么 User
table 甚至不存在,因此查询会出错。
设置默认用户的逻辑应该放在视图(或 Django 管理)而不是模型文件中。
在管理员中,您可以定义一个自定义表单来设置 creator
字段的初始值。
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
try:
user = User.objects.get(username="antoni4040")
kwargs['initial']['creator'] = user
except MyModel.DoesNotExist:
pass
super(MyModelForm, self).__init__(*args, **kwargs)
然后在您的管理员中使用该模型表单。
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
...
如果您真的想这样做,您可以打开一个 shell 并获取该用户的 ID,然后将默认值设置为该 ID。
问题是,你为什么要这么做?第一次添加模型时,它将正确使用默认值。第二次尝试这样做时,它会失败,因为它是一对一的,而不是多对一的,所以它会失败。
我有一个模型,我想添加一个 OneToOneField 来保存对象的创建者: models.py
creator = models.OneToOneField(User, blank=True,
default=User.objects.filter(
username="antoni4040"))
我已经有一个包含项目的数据库,只希望默认值为管理员用户,该用户的用户名为 "antoni4040"。当我尝试在没有默认字段的情况下进行迁移时,它会要求提供默认值,所以我无法摆脱它。但这是 运行 makemigrations 时我得到的:
Migrations for 'jokes_app':
0008_joke_creator.py:
- Add field creator to joke
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 150, in handle
self.write_migration_files(changes)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 178, in write_migration_files
migration_string = writer.as_string()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 167, in as_string
operation_string, operation_imports = OperationWriter(operation).serialize()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 124, in serialize
_write(arg_name, arg_value)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 88, in _write
arg_string, arg_imports = MigrationWriter.serialize(_arg_value)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 433, in serialize
return cls.serialize_deconstructed(path, args, kwargs)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 318, in serialize_deconstructed
arg_string, arg_imports = cls.serialize(arg)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 517, in serialize
item_string, item_imports = cls.serialize(item)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 540, in serialize
"topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: <User: antoni4040>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/1.9/topics/migrations/#migration-serializing
我做错了什么?
您正在使用查询集User.objects.filter(username="antoni4040")
。要获取模型实例,您可以使用 User.objects.get(username="antoni4040")
.
但是,您不应将模型实例用作模型字段中的默认值。如果用户不存在于数据库中,则没有错误处理。事实上,如果 models.py
在 运行 初始迁移之前加载,那么 User
table 甚至不存在,因此查询会出错。
设置默认用户的逻辑应该放在视图(或 Django 管理)而不是模型文件中。
在管理员中,您可以定义一个自定义表单来设置 creator
字段的初始值。
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
try:
user = User.objects.get(username="antoni4040")
kwargs['initial']['creator'] = user
except MyModel.DoesNotExist:
pass
super(MyModelForm, self).__init__(*args, **kwargs)
然后在您的管理员中使用该模型表单。
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
...
如果您真的想这样做,您可以打开一个 shell 并获取该用户的 ID,然后将默认值设置为该 ID。
问题是,你为什么要这么做?第一次添加模型时,它将正确使用默认值。第二次尝试这样做时,它会失败,因为它是一对一的,而不是多对一的,所以它会失败。