Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

462
Vistas
Django 3 - Model.save() when providing a default for the primary key

I'm working on upgrading my project from Django 2 to Django 3, I have read their release notes of Django 3 and there is a point that I don't really understand what it will impact to my current project. Here they say:

enter image description here

As I understand, if we try to call Model.save(), it would always create a new record instead of updating if the model is an existing record. For example:

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.

I have had an experimented and it is still the same behaviour as Django 2, not sure what they mean.

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)

Update:

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)

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

It should be read carefully

no longer attempts to find a row when saving a new Model instance and a default value for the primary key is provided,

So in case you are going to create new object with id that is already in database it would now fail instead of having behavior similar to update_or_create as it will now preform INSERT statement instead of UPDATE

over 4 years ago · Santiago Trujillo Denunciar

0

Consider this example. Suppose we have a simple model as

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)

The main thing I have done in this example is, I did set a default callable function for Primary Keys. Also, I returned only a single value from the function, for the sake of demonstration.

## 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"

Conclusion

In Django<3.0, the Model.save() will do an update or insert operation if there is a PK value associated with the model instance whereas in Django>=3.0, only perform an insert operation hence the UNIQUE constraint failed exception.

Impact of this change in the current project

Since this Django change is only applicable when a new instance is created and we usually don't set any default value functions for Primary Keys.

In short, this change will not make any problem unless you are providing default value during model instance creation.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda