1

I have been struggling all morning trying to figure out how to compare two different querysets. I have two manytomanyfields in my model, and I'm trying to figure out if they are identical.

I research this by viewing this particular issue: How do I test Django QuerySets are equal?

I am using class based views...and I have a model with two manytomanyfields...

My model...

class Author(models.Model):

title = models.ManyToManyField(User,blank=True,related_name='title')
title1 = models.ManyToManyField(User,blank=True,related_name='title1)

My View...

class AuthorDetailView(DetailView):
    model = Author 

def get_context_data(self, **kwargs):
    context = super(AuthorDetailView, self).get_context_data(**kwargs)
    title = list(Author.objects.filter(title))
    title1 = list(Author.objects.filter(title1))
    test_instance = Author.objects.all()
    proxy4 = self.assertQuerySetEqual(Author.objects.all(), map(repr, [test_instance]))

I am trying to compare fields title and title1. However when try to run the code above I continually get a 'View' object has no attribute 'assertQuerysetEqual'. I can't even get this function to work. I running Django 1.11 and Postgresql. Perhaps this function doesn't work with Postgresql? Any help to get me on the right track is appreciated. Been playing with this and researching all morning with no luck. Thanks in advance.

Update...I have also been playing with various versions of trying to compare title_set.all and title1_set.all in the views....this is working intermittently...but the two are always returning that they are equal.

Steve Smith
  • 1,019
  • 3
  • 16
  • 38

2 Answers2

4

self.assertQuerySetEqual is about unit-testing.

All you need is compare two lists in your view. It can be done with sets.

set(title) == set(title1)
Danil
  • 4,781
  • 1
  • 35
  • 50
  • Thank you for the suggestion. I'm still struggling on how to incorporate this into a class based view. I can figure it out with a function view...but thoughts on how to do it in a Class Based DetailView? – Steve Smith Jan 09 '19 at 20:09
2

Your AuthorDetailView need to inherits from django.test.TestCase in order to get access to self.assertQuerySetEqual which is a testing feature.

So basically you need to do like this example:

from django.test import TestCase
...

class AuthorDetailView(DetailView, TestCase):
    ...

Otherwise for comparing two lists you can use set() like what @Daniil Mashkin said in his answer.

So, more in depth, you can do something like this:

class AuthorDetailView(DetailView):
    model = Author 

def get_context_data(self, **kwargs):
    context = super(AuthorDetailView, self).get_context_data(**kwargs)
    title = list(Author.objects.all().values_list('title'))
    title1 = list(Author.objects.all().values_list('title1'))
    # test if the two lists are equal
    equal_ = set(title) == set(title1)
    # add the result to the context variable
    context.update({'titles_are_equal': equal_})
    # return it in order to get the variable `title_are_equal` 
    # into your template
    return context

For more informations visit the django official documentaiton

Chiheb Nexus
  • 9,104
  • 4
  • 30
  • 43
  • So I'm trying to do this in production, test if the values are the same for the two fields in question. Is this only supposed to be used for Testing or is it ok to use it in production as well? – Steve Smith Jan 09 '19 at 21:15
  • 1
    @SteveSmith, no only in testing. In production use `set()` then add the rest of your comparison logic in the view or in the template. The testing suit is only meant for testing environment to catch the bug before going to production. – Chiheb Nexus Jan 09 '19 at 21:17
  • 1
    The code above worked. For my use case, I needed to alter the title = list(Author.objects.all().values_list('title')) to Author.objects.filter(id=self.object.pk).values_list('title')) and then it worked as I needed it to. Thanks to Chiheb Nexus! – Steve Smith Jan 09 '19 at 22:22