python - Django 3 - 为主键提供默认值时的 Model.save()

标签 python django django-3.0

我正在将我的项目从 Django 2 升级到 Django 3,我已经阅读了他们的 release notes of Django 3还有a point我真的不明白它会对我当前的项目产生什么影响。他们在这里说:

enter image description here

据我了解,如果我们尝试调用 Model.save() ,如果模型是现有记录,它将始终创建新记录而不是更新。例如:

car = Car.objects.first()
car.name = 'Honda'
car.save() # does it INSERT or UPDATE? I suspect it is an "INSERT" statement as their explanation and "UPDATE" statement in Django 2.

我已经进行了实验,它仍然与 Django 2 的行为相同,不确定它们的含义。
In [5]: u = User.objects.first()                                                                                                                                                                          
(0.001) SELECT "accounts_user"."id", "accounts_user"."password", "accounts_user"."last_login", "accounts_user"."is_superuser", "accounts_user"."username", "accounts_user"."first_name", "accounts_user"."last_name", "accounts_user"."is_staff", "accounts_user"."is_active", "accounts_user"."date_joined", "accounts_user"."email", "accounts_user"."avatar", "accounts_user"."last_location"::bytea, "accounts_user"."uuid", "accounts_user"."country", "accounts_user"."city", "accounts_user"."phone" FROM "accounts_user" ORDER BY "accounts_user"."id" ASC LIMIT 1; args=()

In [6]: u.save()                                                                                                                                                                                          
(0.006) UPDATE "accounts_user" SET "password" = 'pbkdf2_sha256_sha512$180000$FbFcNuPMrOZ6$GwIftEo+7+OpsORwn99lycye46aJn/aJNAtc50N478Y=', "last_login" = NULL, "is_superuser" = false, "username" = 'email0@mail.com', "first_name" = 'Noah', "last_name" = 'Spencer', "is_staff" = false, "is_active" = true, "date_joined" = '2020-05-12T07:06:20.605650+00:00'::timestamptz, "email" = 'email0@mail.com', "avatar" = 'account/user_avatar/example_HseJquC.jpg', "last_location" = NULL, "uuid" = 'f6992866-e476-409e-9f1b-098afadce5b7'::uuid, "country" = NULL, "city" = NULL, "phone" = NULL WHERE "accounts_user"."id" = 1; args=('pbkdf2_sha256_sha512$180000$FbFcNuPMrOZ6$GwIftEo+7+OpsORwn99lycye46aJn/aJNAtc50N478Y=', False, 'email0@mail.com', 'Noah', 'Spencer', False, True, datetime.datetime(2020, 5, 12, 7, 6, 20, 605650, tzinfo=<UTC>), 'email0@mail.com', 'account/user_avatar/example_HseJquC.jpg', UUID('f6992866-e476-409e-9f1b-098afadce5b7'), 1)

更新:
In [38]: u1 = User.objects.first()                                                                                                                                                                        
(0.000) SELECT "accounts_user"."id", "accounts_user"."password", "accounts_user"."last_login", "accounts_user"."is_superuser", "accounts_user"."username", "accounts_user"."first_name", "accounts_user"."last_name", "accounts_user"."is_staff", "accounts_user"."is_active", "accounts_user"."date_joined", "accounts_user"."email", "accounts_user"."avatar", "accounts_user"."last_location"::bytea, "accounts_user"."uuid", "accounts_user"."country", "accounts_user"."city", "accounts_user"."phone" FROM "accounts_user" ORDER BY "accounts_user"."id" ASC LIMIT 1; args=()

In [39]: u1.pk                                                                                                                                                                                            
Out[39]: 1

In [40]: u2 = User(pk=1)                                                                                                                                                                                  

In [41]: u2.email = 'email@email.com'                                                                                                                                                                     

In [42]: u2.save()                                                                                                                                                                                        
(0.006) UPDATE "accounts_user" SET "password" = '', "last_login" = NULL, "is_superuser" = false, "username" = 'email@email.com', "first_name" = '', "last_name" = '', "is_staff" = false, "is_active" = true, "date_joined" = '2020-05-13T01:20:47.718449+00:00'::timestamptz, "email" = 'email@email.com', "avatar" = '', "last_location" = NULL, "uuid" = '89ba0924-03a7-44d2-bc6d-5fd2dcb0de0b'::uuid, "country" = NULL, "city" = NULL, "phone" = NULL WHERE "accounts_user"."id" = 1; args=('', False, 'email@email.com', '', '', False, True, datetime.datetime(2020, 5, 13, 1, 20, 47, 718449, tzinfo=<UTC>), 'email@email.com', '', UUID('89ba0924-03a7-44d2-bc6d-5fd2dcb0de0b'), 1)

最佳答案

考虑这个例子。假设我们有一个简单的模型

CONSTANT = 10


def foo_pk_default():
    return CONSTANT


class Foo(models.Model):
    id = models.IntegerField(primary_key=True, default=foo_pk_default)
    name = models.CharField(max_length=10)

我在这个例子中所做的主要事情是,我确实为主键设置了默认的可调用函数 .此外,为了演示,我只从函数返回了一个值。
## Django 2.2
In [5]: foo_instance_1 = Foo(name='foo_name_1')

In [6]: foo_instance_1.save()

In [7]: print(foo_instance_1.__dict__)
{'_state': , 'id': 10, 'name': 'foo_name_1'}

In [8]: foo_instance_2 = Foo(name='foo_name_2')

In [9]: foo_instance_2.save()

In [10]: print(foo_instance_2.__dict__)
{'_state': , 'id': 10, 'name': 'foo_name_2'}

## Django 3.X
In [6]: foo_instance_1 = Foo(name='foo_name_1')

In [7]: foo_instance_1.save()

In [8]: print(foo_instance_1.__dict__)
{'_state': , 'id': 10, 'name': 'foo_name_1'}

In [9]: foo_instance_2 = Foo(name='foo_name_2')

In [10]: foo_instance_2.save()
# Raised "IntegrityError: UNIQUE constraint failed: music_foo.id"

结论

Django<3.0 , Model.save() 会做一个更新或插入操作如果有一个与模型实例相关联的 PK 值,而在 Django>=3.0 , 只执行 插入操作 因此 UNIQUE constraint failed异常(exception)。

此更改对当前项目的影响

由于此 Django 更改仅适用于 新实例已创建 我们通常不会为 Primary Keys 设置任何默认值函数。

简而言之,除非您在模型实例创建期间提供默认值,否则此更改不会产生任何问题。

关于python - Django 3 - 为主键提供默认值时的 Model.save(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61754736/

相关文章:

python - Django:使用 sudo 在虚拟环境中运行服务器

django - 我可以告诉一下django TestClient是否正在调用 View 吗

python - Django 模型线程安全吗?

html - Django 模板转换 datetime-local 格式

python - AWS S3 存储桶 Django 3.0 用户配置文件图像上传访问错误

python - Django:按计数排序的聚合的输出聚合

python - 如何调整多 channel tiff 图像的大小?

python - 如何让 Python FastAPI 异步/等待功能正常工作?

python - 如何填充 NAN "ignoring"索引?

python - 属性错误 : module 'django.db.models' has no attribute 'RegexField' . python (django)