7

I have a class as

class PlaylistManager(models.Manager):
    def add_playlist(self, name):
        playlist = Playlist(name=name)
        playlist.save()
        return playlist

    def get_playlist_with_id(self, id):
        return super(PlaylistManager, self).get_query_set().filter(pk=id)

class Playlist(models.Model):
    name = models.CharField(max_length=30)
    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    deleted = models.BooleanField(default=False)
    objects = PlaylistManager() # is a customer manager

    def __repr__(self):
        return '<Playlist name:%s, date_created:%s, date_modified:%s, deleted:%s>' % \
                (self.name, self.date_created, self.date_modified, self.deleted)

    class Meta:
        db_table = 'playlists'

and i test as

def test_get_playlist(self):
    playlist = Utility.add_playlist()
    self.assertEqual(Playlist.objects.get_playlist_with_id(playlist.id), playlist)

class Utility():
    @staticmethod
    def add_playlist(playlist_name=PLAYLIST):
        return Playlist.objects.add_playlist(playlist_name)

When I run the test, I see error as

AssertionError: [<Playlist name:playlist, date_created:2012-07-18 19:54:12.265909+00:00, date_modified:2012-07-18 19:54:12.265955+00:00, deleted:False>] != <Playlist name:playlist, date_created:2012-07-18 19:54:12.265909+00:00, date_modified:2012-07-18 19:54:12.265955+00:00, deleted:False>

even when the two objects are same.

Is there anything I am missing here?

daydreamer
  • 87,243
  • 191
  • 450
  • 722
  • It must not be the same object. Try comparing `id(Playlist.objects.get_playlist_with_id(playlist.id))` and `id(playlist)`. Just because the information contained in them is the same does not mean they are the same object (that is, that `obj1 == obj2`) – David Robinson Jul 18 '12 at 20:03
  • 1
    Even though they're phrased differently, I think this is essentially a duplicate of http://stackoverflow.com/questions/2513342/django-comparing-model-instances-for-equality – kojiro Jul 18 '12 at 20:07

3 Answers3

16

assertEqual() uses the == operator to compare the classes. The default == operator of user-defined classes compares instances by object identity. This means two instances are only considered equal when they are the same instance.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • 4
    This answer could be improved by mentioning the `__eq__` operator. In fact, `lambda self, other: self.pk == other.pk` might not be a terrible implementation. – kojiro Jul 18 '12 at 20:11
  • 1
    @kojiro: I don't think it is a good idea to define `__eq__()` when the only place where it is used is in the unit tests, so I won't update my answer. – Sven Marnach Jul 18 '12 at 20:18
  • Why is it throwing an error, though; and not asserting to False? – M.Ionut Feb 06 '22 at 13:52
  • 1
    @M.Ionut It's the whole point of an assertion that it throws and `AssertionError` if the assertion fails. Not sure what "asserting to False" means. – Sven Marnach Feb 07 '22 at 10:27
  • @SvenMarnach you're right, my bad. Sorry and thanks for pointing it out! – M.Ionut Feb 07 '22 at 19:16
4

Compare model id or pk and it will be ok.

3

The AssertionError is correct. Your get_playlist_with_id returns a Queryset not a Playlist instance. If you want get_playlist_with_id to return the single instance then you should use get not filter.

Mark Lavin
  • 24,664
  • 5
  • 76
  • 70