it-roy-ru.com

Как мне проверить, равны ли Django QuerySets?

Я пытаюсь проверить свои взгляды на Джанго. Это представление передает QuerySet в шаблон:

def merchant_home(request, slug):
  merchant = Merchant.objects.get(slug=slug)
  product_list = merchant.products.all()
  return render_to_response('merchant_home.html',
                            {'merchant': merchant,
                            'product_list': product_list},
                            context_instance=RequestContext(request))

и проверить:

  def test(self):
    "Merchant home view should send merchant and merchant products to the template"
    merchant = Merchant.objects.create(name='test merchant')
    product = Product.objects.create(name='test product', price=100.00)
    merchant.products.add(product)

    test_client = Client()
    response = test_client.get('/' + merchant.slug)
    # self.assertListEqual(response.context['product_list'], merchant.products.all())
    self.assertQuerysetEqual(response.context['product_list'], merchant.products.all())

РЕДАКТИРОВАТЬ Я использую self.assertQuerysetEqual вместо self.assertListEqual. К сожалению, это все еще не работает, и терминал отображает это: ['<Product: Product object>'] != [<Product: Product object>]


assertListEqual повышает: объект 'QuerySet' не имеет атрибута 'разность' assertEqual также не работает, хотя self.assertSetEqual(response.context['product_list'][0], merchant.products.all()[0]) проходит.

Я предполагаю, что это потому, что QuerySets - это разные объекты, даже если они содержат одинаковые экземпляры модели. 

Как проверить, что два QuerySet содержат одинаковые данные? Я каждый проверяю это правильно? Это мой 4-й день обучения Джанго, поэтому я хотел бы узнать лучшие практики, если это возможно. Благодарю.

23
jz999

Используйте assertQuerysetEqual , который построен для сравнения двух наборов запросов для вас. Вам нужно будет создать подкласс Django Django.test.TestCase, чтобы он был доступен в ваших тестах.

23
girasquid

По умолчанию assertQuerysetEqual использует repr() в первом аргументе. Вот почему у вас возникли проблемы со строками в сравнении наборов запросов.

Чтобы обойти это, вы можете переопределить аргумент transform с помощью функции lambda, которая не использует repr():

self.assertQuerysetEqual(queryset_1, queryset_2, transform=lambda x: x)
16
dspacejs

У меня просто была такая же проблема. Второй аргумент assertQuerysetEqual должен быть списком ожидаемых repr () в виде строк. Вот пример из набора тестов Django:

self.assertQuerysetEqual(c1.tags.all(), ["<Tag: t1>", "<Tag: t2>"], ordered=False)
8
sk1p

Я решил эту проблему, используя map - repr() каждую запись в наборе запросов внутри вызова self.assertQuerysetEqual, например,.

self.assertQuerysetEqual(queryset_1, map(repr, queryset_2))
3
DrBuck

Альтернативный, но не обязательно лучший метод может выглядеть следующим образом (например, тестирование контекста в представлении) при использовании pytest:

all_the_things = Things.objects.all()
assert set(list(response.context_data['all_the_things'])) == set(list(all_the_things))

Это преобразует его в список, затем в набор, который напрямую сопоставим с другим набором. Будьте осторожны с поведением set, однако, это может быть не совсем то, что вам нужно, поскольку он удалит дубликаты.

1
Chris

Я обнаружил, что использование self.assertCountEqual(queryset1, queryset2) также решает проблему. 

0
Salvatore Fiorenza