且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在Django中使用InlineAdmin和post_save信号创建配置文件模型

更新时间:2022-12-05 20:49:35

可以通过将 primary_key = True OneToOneField 指向用户模型,就像您已经弄清楚一样。

The problem can be avoided by setting primary_key=True on the OneToOneField pointing at the User model, as you have figured out yourself.

这个工作原理似乎很简单。

The reason that this works seems to be rather simple.

当您尝试创建一个模型实例并设置 pk 手动保存之前,Django将尝试使用 pk 在数据库中查找记录,并进行更新,而不是盲目地尝试创建一个新的。如果没有,则按预期创建新记录。

When you try to create a model instance and set the pk manually before saving it, Django will try to find a record in the database with that pk and update it rather than blindly attempting to create a new one. If none exists, it creates the new record as expected.

当您将 OneToOneField 设置为主键时, Django Admin将该字段设置为相关的用户模型的ID,这意味着 pk 已经设置,Django会尝试找到现有记录。

When you set the OneToOneField as the primary key and Django Admin sets that field to the related User model's ID, that means the pk is already set and Django will attempt to find an existing record first.

这是将 OneToOneField 设置为主键的情况:

This is what happens with the OneToOneField set as primary key:


  1. Django管理员创建新的用户实例,没有 id

  2. Django Admin保存用户实例。
  1. Django Admin creates the new User instance, with no id.
  2. Django Admin saves the User instance.

  1. 因为 pk (在这种情况下 id )是未设置,Django尝试创建新记录。

  2. 新记录的 id 由数据库自动设置。

  3. post_save 钩子为该用户创建一个新的配置文件实例实例。

  1. Because the pk (in this case id) is not set, Django attempts to create a new record.
  2. The new record's id is set automatically by the database.
  3. The post_save hook creates a new Profile instance for that User instance.


  • Django管理员创建新的个人资料实例,其用户设置为用户的 id

  • Django管理员将保存配置文件实例。

  • Django Admin creates the new Profile instance, with its user set to the user's id.
  • Django Admin saves the Profile instance.

    1. 因为 pk (在这种情况下 user )是已经设置好,Django尝试使用 pk 获取现有记录。

    2. Django查找现有记录并对其进行更新。 >
    1. Because the pk (in this case user) is already set, Django attempts to fetch an existing record with that pk.
    2. Django finds the existing record and updates it.


  • 如果没有显式设置主键,Django会添加一个使用数据库的 auto_increment 功能:数据库将 pk 设置为不存在的下一个最大值。这意味着该字段实际上将保留为空白,除非您手动设置,否则Django将始终尝试插入新记录,导致与 OneToOneField 之间的唯一性约束产生冲突>。

    If you don't set the primary key explicitly, Django instead adds a field that uses the database's auto_increment functionality: the database sets the pk to the next largest value that doesn't exist. This means the field will actually be left blank unless you set it manually and Django will therefore always attempt to insert a new record, resulting in a conflict with the uniqueness-constraint on the OneToOneField.

    这是原始问题的原因:


    1. Django管理员创建新的用户实例,没有 id

    2. Django Admin保存用户实例, post_save 钩子创建一个新的配置文件实例如前所述。

    3. Django管理员创建新的个人资料实例,没有 id ($自动添加 pk 字段)。

    4. Django Admin保存个人资料实例。
    1. Django Admin creates the new User instance, with no id.
    2. Django Admin saves the User instance, the post_save hook creating a new Profile instance as before.
    3. Django Admin creates the new Profile instance, with no id (the automatically added pk field).
    4. Django Admin saves the Profile instance.

    1. 因为 pk (在这种情况下 id )是没有设置,Django尝试创建一个新的记录。

    2. 数据库报告了对用户字段的表的唯一性约束的违反。

    3. Django会抛出异常。你今天不会去太空。

    1. Because the pk (in this case id) is not set, Django attempts to create a new record.
    2. The database reports a violation of the table's uniqueness-constraint on the user field.
    3. Django throws an Exception. You will not go to space today.