Modelo de Django () frente a Modelo.objetos.crear ()

6 minutos de lectura

avatar de usuario
0 pierna

Cuál es la diferencia entre ejecutar dos comandos:

foo = FooModel()

y

bar = BarModel.objects.create()

¿El segundo crea inmediatamente un BarModel en la base de datos, mientras que para FooModella save() ¿Se debe llamar explícitamente al método para agregarlo a la base de datos?

  • Sí, esa es la diferencia.

    – Daniel Rosemann

    31 de octubre de 2014 a las 10:14

  • ¿Es siempre cierto? He visto lugares en la documentación de Django donde llaman a save() en una instancia después de crearla a través de *.objects.create(). Como aquí docs.djangoproject.com/en/3.1/topics/db/models/…

    – Aleksandr Mikheev

    16 de febrero de 2021 a las 8:12

avatar de usuario
madzohan

https://docs.djangoproject.com/en/stable/topics/db/queries/#creating-objects

Para crear y guardar un objeto en un solo paso, use el create() método.

  • En mi opinión, los documentos de Django son un poco contradictorios en este punto. Tuve la misma pregunta y leí “Tenga en cuenta que la creación de instancias de un modelo de ninguna manera toca su base de datos; para eso, debe guardar ()”. docs.djangoproject.com/en/1.10/ref/models/instances/…

    – ceros

    27 de enero de 2017 a las 12:50

  • No lo veo como contradictorio. En general, en python, crea instancias de objetos colocando corchetes después del nombre de los objetos, no mediante un método de creación

    – danidee

    24/03/2017 a las 18:10

  • @danidee Estoy de acuerdo en que no es contradictorio, pero ciertamente es engañoso. Principalmente porque en el enlace de Nils, el ejemplo 1 es “instanciación” pero el ejemplo 2 es “instanciación+guardado”. Además, ¿por qué debería consultar el documento de “consultas” cuando quiero saber cómo guardar un modelo? Realmente hay muchos dolores en django doc.

    – Nakamura

    3 de junio de 2018 a las 19:27


  • @Nakamura porque INSERT es una consulta?

    – Juanjo Conti

    28 de noviembre de 2018 a las 20:18

  • @madzohan Creo que los documentos cambiaron exactamente al contrario: “Para crear un objeto, ejecútelo usando argumentos de palabras clave para la clase modelo, luego llame a save() para guardarlo en la base de datos”.

    – Martín Tomas

    8 de julio de 2021 a las 13:13

avatar de usuario
Furkan Siddiqui

Las diferencias entre Model() y Model.objects.create() son los siguientes:


  1. INSERTAR vs ACTUALIZAR

    Model.save() INSERTA o ACTUALIZA un objeto en una base de datos, mientras que Model.objects.create() solo INSERTAR.

    Model.save() lo hace

    • ACTUALIZAR Si el atributo de clave principal del objeto se establece en un valor que se evalúa como True

    • INSERTAR Si el atributo de clave principal del objeto no está configurado o si la ACTUALIZACIÓN no actualizó nada (por ejemplo, si la clave principal está configurada en un valor que no existe en la base de datos).


  1. Clave principal existente

    Si el atributo de clave principal se establece en un valor y dicha clave principal ya existe, entonces Model.save() realiza UPDATE, pero Model.objects.create() aumenta IntegrityError.

    Considera lo siguiente modelos.py:

    class Subject(models.Model):
       subject_id = models.PositiveIntegerField(primary_key=True, db_column='subject_id')
       name = models.CharField(max_length=255)
       max_marks = models.PositiveIntegerField()
    
    1. Insertar/Actualizar a db con Model.save()

      physics = Subject(subject_id=1, name="Physics", max_marks=100)
      physics.save()
      math = Subject(subject_id=1, name="Math", max_marks=50)  # Case of update
      math.save()
      

      Resultado:

      Subject.objects.all().values()
      <QuerySet [{'subject_id': 1, 'name': 'Math', 'max_marks': 50}]>
      
    2. Insertar a db con Model.objects.create()

      Subject.objects.create(subject_id=1, name="Chemistry", max_marks=100)
      IntegrityError: UNIQUE constraint failed: m****t.subject_id
      

    Explicación: En el ejemplo, math.save() hace una ACTUALIZACIÓN (cambios name de Física a Matemáticasy max_marks de 100 a 50), porque subject_id es una clave principal y subject_id=1 ya existe en la base de datos. Pero Subject.objects.create() aumenta IntegrityErrorporque, de nuevo la clave principal subject_id con el valor 1 ya existe.


  1. inserción forzada

    Model.save() se puede hacer que se comporte como Model.objects.create() mediante el uso force_insert=True parámetro: Model.save(force_insert=True).


  1. Valor de retorno

    Model.save() devolver None dónde Model.objects.create() instancia de modelo de retorno, es decir package_name.models.Model


Conclusión: Model.objects.create() hace la inicialización del modelo y realiza save() con force_insert=True.

Extracto del código fuente de Model.objects.create()

def create(self, **kwargs):
    """
    Create a new object with the given kwargs, saving it to the database
    and returning the created object.
    """
    obj = self.model(**kwargs)
    self._for_write = True
    obj.save(force_insert=True, using=self.db)
    return obj

Para más detalles sigue los enlaces:

  1. https://docs.djangoproject.com/en/stable/ref/models/querysets/#create

  2. https://github.com/django/django/blob/2d8dcba03aae200aaa103ec1e69f0a0038ec2f85/django/db/models/query.py#L440

  • Esto es mucho mejor y más útil que la respuesta aceptada.

    – jcgoble3

    14 abr a las 15:45

avatar de usuario
Tomas Leonardo

Las dos sintaxis no son equivalentes y puede dar lugar a errores inesperados. Aquí hay un ejemplo simple que muestra las diferencias. Si tienes un modelo:

from django.db import models

class Test(models.Model):

    added = models.DateTimeField(auto_now_add=True)

Y creas un primer objeto:

foo = Test.objects.create(pk=1)

Luego intenta crear un objeto con la misma clave principal:

foo_duplicate = Test.objects.create(pk=1)
# returns the error:
# django.db.utils.IntegrityError: (1062, "Duplicate entry '1' for key 'PRIMARY'")

foo_duplicate = Test(pk=1).save()
# returns the error:
# django.db.utils.IntegrityError: (1048, "Column 'added' cannot be null")

  • asi que .create() crea un objeto incluso si es un campo obligatorio (null=False) ¿Está perdido? Estoy agregando pruebas a mi proyecto y create está teniendo resultados inesperados

    – Vaibhav Vishal

    12 de abril de 2019 a las 13:44

  • No, no debería… Aunque algunos tipos de campo actúan un poco raro en Django. Por ejemplo, CharField incluso si se establece en null=False no generará un error si no se proporciona: esto se debe a que Django establece cadenas de forma predeterminada en una cadena vacía "" entonces no es tecnicamente null

    – Thomas Leonardo

    15 de abril de 2019 a las 15:03

  • sí, solo tengo problemas con los campos de caracteres y el campo de campo (que también es básicamente un campo de caracteres). Usando obj = MyModel()después obj.full_clean() por ahora.

    – Vaibhav Vishal

    16 de abril de 2019 a las 8:13

avatar de usuario
Oleg Belousov

ACTUALIZACIÓN 15.3.2017:

Abrí un tema de Django sobre esto y parece ser aceptado preliminarmente aquí:
https://code.djangoproject.com/ticket/27825

Mi experiencia es que al usar el Constructor (ORM) clase por referencias con Django 1.10.5 puede haber algunas inconsistencias en los datos (es decir, los atributos del objeto creado pueden obtener el tipo de los datos de entrada en lugar del tipo emitido de la propiedad del objeto ORM) ejemplo:

models

class Payment(models.Model):
     amount_cash = models.DecimalField()

some_test.pyobject.create

Class SomeTestCase:
    def generate_orm_obj(self, _constructor, base_data=None, modifiers=None):
        objs = []
        if not base_data:
            base_data = {'amount_case': 123.00}
        for modifier in modifiers:
            actual_data = deepcopy(base_data)
            actual_data.update(modifier)
            # Hacky fix,
            _obj = _constructor.objects.create(**actual_data)
            print(type(_obj.amount_cash)) # Decimal
            assert created
           objs.append(_obj)
        return objs

some_test.pyConstructor()

Class SomeTestCase:
    def generate_orm_obj(self, _constructor, base_data=None, modifiers=None):
        objs = []
        if not base_data:
            base_data = {'amount_case': 123.00}
        for modifier in modifiers:
            actual_data = deepcopy(base_data)
            actual_data.update(modifier)
            # Hacky fix,
            _obj = _constructor(**actual_data)
            print(type(_obj.amount_cash)) # Float
            assert created
           objs.append(_obj)
        return objs

Model.objects.create() crea una instancia de modelo y la guarda. Model() solo crea una instancia de modelo en memoria. No se guarda en la base de datos hasta que llama a la instancia save() método para guardarlo. Ahí es cuando también ocurre la validación.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad