【问题标题】:Django: model OneToOneField with User can't add default valueDjango:带有用户的模型 OneToOneField 无法添加默认值
【发布时间】:2016-07-22 17:08:05
【问题描述】:

我有一个模型,我想添加一个 OneToOneField 来保存对象的创建者: 模型.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

我做错了什么?

【问题讨论】:

    标签: python django database-migration one-to-one


    【解决方案1】:

    您正在使用查询集User.objects.filter(username="antoni4040")。要获取模型实例,您可以使用User.objects.get(username="antoni4040")

    但是,您不应该在模型字段中使用模型实例作为默认值。如果用户在数据库中不存在,则没有错误处理。事实上,如果在运行初始迁移之前加载了 models.py,那么 User 表甚至将不存在,因此查询会出错。

    设置默认用户的逻辑应该放在视图(或 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
        ...
    

    【讨论】:

    • 你能详细说明你的意思吗?
    • 我刚刚添加了“null = True”并删除了默认字段,似乎可以工作但现在我必须手动设置管理员...
    • 我之前没有详细说明,因为您甚至没有说您是否使用管理员。很难回答,因为您没有显示太多代码。我现在添加了一个示例。
    • 我明白你在做什么。您在某种程度上是对的,这很有用,但是您只更改了管理页面,已经存在的项目没有更新创建者值,它只是空值,因为其他任何事情都会导致迁移出现问题...
    • 哦,您希望在运行迁移时设置该值。当./manage.py migrate 提示您输入默认值时,尝试输入用户的 ID(例如 5)。或者,您可以创建 data migration 来设置值。设置好值后,您可以删除 null=True 并创建最终迁移以更新您的模型。
    【解决方案2】:

    如果您真的想这样做,您可以打开一个 shell 并获取该用户的 id,然后将默认设置为那个。

    问题是,你为什么要这样做?第一次添加模型时,它将正确使用默认值。第二次尝试这样做时,它会失败,因为它是一对一的,而不是多对一的,所以它会失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-01
      • 2018-11-01
      • 2022-11-12
      • 1970-01-01
      • 2014-11-27
      • 2018-10-22
      • 2016-05-29
      相关资源
      最近更新 更多