bootstrap - import django template
Django comparando instancias modelo para la igualdad (7)
Entiendo que, con una situación única, puede realizar una operación como:
spam == eggs
y si el spam
y los eggs
son instancias de la misma clase con todos los mismos valores de atributo, devolverá True
. En un modelo de Django, esto es natural porque dos instancias separadas de un modelo nunca serán iguales a menos que tengan el mismo valor .pk
.
El problema con esto es que si una referencia a una instancia tiene atributos que han sido actualizados por middleware en algún punto en el camino y no se ha guardado, y usted está tratando de hacerlo a otra variable que contiene una referencia a una instancia de la mismo modelo, devolverá False
por supuesto, porque tienen diferentes valores para algunos de los atributos. Obviamente no necesito algo como un singleton , pero me pregunto si hay algún método oficial de Djangonic (ha, una nueva palabra) para verificar esto, o si simplemente debo verificar que el valor .pk
sea el mismo con:
spam.pk == eggs.pk
Lo siento si esto fue una gran pérdida de tiempo, pero parece que podría haber un método para hacer esto, y algo que me falta es que lamentaré el camino si no lo encuentro.
ACTUALIZACIÓN (27/02/2015)
Debe ignorar la primera parte de esta pregunta, ya que no debe comparar singletons con ==
, sino con is
. Los Singleton realmente no tienen nada que ver con esta pregunta.
A partir de Django 1.9.7, el código fuente para la igualdad de instancias del modelo es this :
def __eq__(self, other):
if not isinstance(other, Model):
return False
if self._meta.concrete_model != other._meta.concrete_model:
return False
my_pk = self._get_pk_val()
if my_pk is None:
return self is other
return my_pk == other._get_pk_val()
Es decir, dos instancias de modelo son iguales si proceden de la misma tabla de base de datos y tienen la misma clave principal. Si cualquiera de las claves principales es None
, solo son iguales si son el mismo objeto.
(Entonces volviendo a la pregunta del OP, simplemente comparar las instancias estaría bien).
Como comenta orokusaki, "si ninguna instancia tiene una clave principal, volverá a ser verdadera siempre". Si desea que esto funcione, puede ampliar su modelo de la siguiente manera:
def __eq__(self, other):
eq = isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
if eq and self._get_pk_val() is None:
return id(self) == id(other)
return eq
De la documentación de django :
Para comparar dos instancias de modelo, solo use el operador de comparación estándar de Python, el signo doble igual: ==. Detrás de escena, eso compara los valores clave principales de dos modelos.
Puede definir el método de Clase '' __eq__
para __eq__
ese comportamiento:
Sería extraño si dos ejemplos de ejemplares se compararan como iguales si tuvieran atributos diferentes. La mayoría de las veces eso sería indeseable.
Lo que quieres es un caso especial. Comparar spam.pk == eggs.pk
es una buena idea. Si aún no hay pk
, porque no se han guardado, entonces es más difícil definir qué instancias son "realmente" lo mismo si algunos atributos son diferentes.
¿Qué le spam.myid=1
añadir un atributo personalizado a sus instancias cuando las crea, por ejemplo: spam.myid=1
, eggs.myid=2
De esa forma, en algún punto de tu código cuando spamcopy1.seasoning=ketchup
y spamcopy2.seasoning=blackpepper
puedes comparar su atributo myid
para ver si realmente son el "mismo" spam.
Solo para el registro, comparando:
spam == eggs
es peligroso si existe la posibilidad de que cualquiera de ellos sea una instancia de modelo diferida creada por la consulta Model.objects.raw () o por .defer () aplicada a un QuerySet "normal".
Puse más detalles aquí: Problema Django QuerySet .defer () - ¿error o característica?
spam.pk == eggs.pk
es una buena forma de hacerlo.
Puede agregar __eq__
a su modelo pero lo __eq__
porque es confuso ya que ==
puede significar cosas diferentes en contextos diferentes, por ejemplo, quiero que ==
signifique que el contenido es el mismo, el ID puede diferir, así que de nuevo la mejor manera es
spam.pk == eggs.pk
Editar: por cierto en django 1.0.2 La clase de modelo ha definido __eq__
como
def __eq__(self, other):
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
que parece ser el mismo que spam.pk == eggs.pk, ya que pk
es una propiedad que usa _get_pk_val
por lo que no veo por qué el spam == eggs
no funciona.