104👍
From Django documentation:
To compare two model instances, just use the standard Python comparison operator, the double equals sign: ==
. Behind the scenes, that compares the primary key values of two models.
21👍
spam.pk == eggs.pk
is a good way to do that.
You may add __eq__
to your model but I will avoid that, because it is confusing as ==
can mean different things in different contexts, e.g. I may want ==
to mean content is same, id may differ, so again best way is
spam.pk == eggs.pk
Edit:
btw in django 1.0.2 Model class has defined __eq__
as
def __eq__(self, other):
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
which seems to be same as spam.pk == eggs.pk as pk
is property which uses _get_pk_val
so I don’t see why spam == eggs
is not working ?
- [Django]-Can you change a field label in the Django Admin application?
- [Django]-Speeding up Django Testing
- [Django]-Get class name of django model
21👍
The source code for model instance equality is this (from Django 4.0.5):
def __eq__(self, other):
if not isinstance(other, Model):
return NotImplemented
if self._meta.concrete_model != other._meta.concrete_model:
return False
my_pk = self.pk
if my_pk is None:
return self is other
return my_pk == other.pk
That is, two model instances are equal if they come from the same database table and have the same primary key. If either primary key is None
they’re only equal if they’re the same object.
(So getting back to the OP’s question, simply comparing the instances would be fine.)
- [Django]-Group by Foreign Key and show related items – Django
- [Django]-WARNING: Running pip as the 'root' user
- [Django]-Are there any plans to officially support Django with IIS?
7👍
You can define the Class’ __eq__
method to chage that behaviour:
- [Django]-Mac OS X – EnvironmentError: mysql_config not found
- [Django]-How do I create sub-applications in Django?
- [Django]-Complete django DB reset
4👍
Just for the record, comparing:
spam == eggs
is dangerous if there is any chance that either of them could be a deferred model instance created by Model.objects.raw() query or by .defer() applied to a ‘normal’ QuerySet.
I put more details here: Django QuerySet .defer() problem – bug or feature?
- [Django]-Setting the selected value on a Django forms.ChoiceField
- [Django]-How do I send empty response in Django without templates
- [Django]-How to check if ManyToMany field is not empty?
2👍
from https://djangosnippets.org/snippets/2281/
i changed to compare two instance and return Boolean value
def is_same(self, obj):
excluded_keys = 'timestamp', 'creator_id' # creater_id is one foreign key ins table
return _is_same(self, obj, excluded_keys)
def _is_same(obj1, obj2, excluded_keys):
d1, d2 = obj1.__dict__, obj2.__dict__
for k, v in d1.items():
# print('check key: ' + k)
if k in excluded_keys or k in ['_state', '_django_cleanup_original_cache']: # _state make difference so automatically exclude it
# print(k + ' is in excluded keys')
continue
if v != d2[k]:
# print('value in not equal in second object')
return False
else:
# print('it is same')
continue
# print('all keys checked, so both object is same')
return True
- [Django]-Django: show a ManyToManyField in a template?
- [Django]-Django model with 2 foreign keys from the same table
- [Django]-How to manually assign imagefield in Django
1👍
As orokusaki comments, “if neither instance has a primary key, it will return true always”. If you want this to work, you could extend your model like so:
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
- [Django]-Site matching query does not exist
- [Django]-Django Framework – Is there a shutdown event that can be subscribed to?
- [Django]-How do I create sub-applications in Django?
0👍
It would be strange if two model instances compared as equal if they had different attributes. Most of the time that would be undesirable.
What you want is a special case. Comparing spam.pk == eggs.pk
is a good idea. If there’s no pk
yet, because they haven’t been saved, then it’s harder to define which instances are “really” the same if some attributes are different.
How about adding a custom attribute to your instances when creating them, eg:
spam.myid=1
, eggs.myid=2
That way at some point in your code when spamcopy1.seasoning=ketchup
and spamcopy2.seasoning=blackpepper
you can compare their myid
attribute to see if they’re really the “same” spam.
- [Django]-Multiple Database Config in Django 1.2
- [Django]-Django: dependencies reference nonexistent parent node
- [Django]-How to resolve AssertionError: .accepted_renderer not set on Response in django and ajax