代码之家  ›  专栏  ›  技术社区  ›  Antoni4040

Django:带有User的model OneToOneField无法添加默认值

  •  1
  • Antoni4040  · 技术社区  · 8 年前

    我有一个模型,我想添加一个OneToOneField来保存对象的创建者: 型号.py

    creator = models.OneToOneField(User, blank=True,
                                   default=User.objects.filter(
                                       username="antoni4040"))
    

    我已经有了一个包含项目的数据库,只希望默认值为admin用户,用户名为“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
    

    我做错了什么?

    2 回复  |  直到 8 年前
        1
  •  1
  •   Alasdair    8 年前

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

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

    设置默认用户的逻辑应该放在视图(或Django admin)中,而不是放在模型文件中。

    在admin中,您可以定义一个自定义表单,该表单为 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
        ...
    
        2
  •  0
  •   wonton    6 年前

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

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