from django.conf import settings
from django.utils.functional import cached_property
from regulus_oscar.apps.catalogue.abstract_models import AbstractProduct
class Product(AbstractProduct):
def __str__(self):
"""
Appends the variant-identifier product attribute values to the string
representation of child products, for use in multiple places, including
on the front end and dashboard, and in emails to customers and the
merchant.
"""
if self.is_child and self.variant_attribute_summaries:
# The parent "__str__" method appends a summary of all the product
# attribute values, whereas we only want to include a summary of the
# variant-identifier ones
return f"{ self.title if self.title else self.parent.title } ({ self.variant_attribute_summaries })"
else:
return super().__str__()
def get_title(self):
"""
Appends the variant-identifier product attribute values to the title of
child products, for use in multiple places, including on the front end
and dashboard, and in emails to customers and the merchant.
"""
title = super().get_title()
if self.is_child and self.variant_attribute_summaries:
title = f"{ title } ({ self.variant_attribute_summaries })"
return title
get_title.short_description = "Title"
@cached_property
def variant_attribute_summaries(self):
"""
Returns a string of a product's variant-identifier ("Colour" and "Size")
product attribute values.
"""
return ", ".join(
[
product_attribute_value.summary()
for product_attribute_value in self.get_attribute_values().filter(
attribute__name__in=settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES
)
]
)
from regulus_oscar.apps.catalogue.models import * # noqa isort:skip
Above is my models.py file and everything works as expected on the front-end side of things however when I run the tests below I have some errors and I believe they are being caused by the @cached_property. How can I fix this issue for testing purposes and have it deployed to production without issues? I need the @cached_property to avoid calling the database every time since its a very large project and this will cause the site to slow down significantly
import pytest
from regulus_oscar.test.factories import (
ProductAttributeFactory,
ProductAttributeValueFactory,
ProductClassFactory,
ProductFactory,
)
@pytest.mark.django_db
def test_product_get_title_without_variant_attribute_summaries_for_child_products(settings):
settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
product_class = ProductClassFactory(name="Foo")
parent_product = ProductFactory(structure="parent", product_class=product_class)
child_product = ProductFactory(structure="child", parent=parent_product, title = 'Foobar')
assert child_product.get_title() == 'Foobar'
@pytest.mark.django_db
def test_variant_attribute_summaries_returns_string_when_variant_attributes_exist_for_child_products(settings):
settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
product_class = ProductClassFactory(name="Foo")
colour_attribute = ProductAttributeFactory(product_class=product_class, name="Colour", code="colour", type="color")
size_attribute = ProductAttributeFactory(product_class=product_class, name="Size", code="size", type="text")
parent_product = ProductFactory(structure="parent", product_class=product_class)
child_product = ProductFactory(structure="child", parent=parent_product, title='Foobar')
red = ProductAttributeValueFactory(attribute=colour_attribute, product=child_product, value_text="#ff0000")
small = ProductAttributeValueFactory(attribute=size_attribute, product=child_product, value_text="Small")
attribute_summary = child_product.variant_attribute_summaries
assert attribute_summary == 'Colour: #ff0000, Size: Small'
@pytest.mark.django_db
def test_variant_attribute_summaries_returns_empty_string_when_variant_attributes_do_not_exist_for_child_product(settings):
settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
product_class = ProductClassFactory(name="Foo")
parent_product = ProductFactory(structure="parent", product_class=product_class)
child_product = ProductFactory(structure="child", parent=parent_product)
attribute_summary = child_product.variant_attribute_summaries
assert attribute_summary == ''
@pytest.mark.django_db
def test_variant_attribute_summaries_returns_string_when_variant_attributes_exist_for_parent_products(settings):
settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
product_class = ProductClassFactory(name="Foo")
colour_attribute = ProductAttributeFactory(product_class=product_class, name="Colour", code="colour", type="color")
size_attribute = ProductAttributeFactory(product_class=product_class, name="Size", code="size", type="text")
parent_product = ProductFactory(structure="parent", product_class=product_class, title="Parent Product")
red = ProductAttributeValueFactory(attribute=colour_attribute, product=parent_product, value_text="#ff0000")
small = ProductAttributeValueFactory(attribute=size_attribute, product=parent_product, value_text="Small")
assert parent_product.variant_attribute_summaries == 'Colour: #ff0000, Size: Small'
@pytest.mark.django_db
def test_variant_attribute_summaries_returns_empty_string_when_variant_attributes_do_not_exist_for_parent_products(settings):
settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
product_class = ProductClassFactory(name="Foo")
parent_product = ProductFactory(structure="parent", product_class=product_class)
attribute_summary = parent_product.variant_attribute_summaries
assert attribute_summary == ''
@pytest.mark.django_db
def test_product_get_title_without_variant_attribute_summaries_for_parent_products(settings):
settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
product_class = ProductClassFactory(name="Foo")
parent_product = ProductFactory(structure="parent", product_class=product_class, title = 'Foobar')
assert parent_product.get_title() == 'Foobar'
@pytest.mark.django_db
def test_str__for_product_without_variant_attribute_summaries_for_parent_products(settings):
settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
product_class = ProductClassFactory(name="Foo")
colour_attribute = ProductAttributeFactory(product_class=product_class, name="Colour", code="colour", type="color")
size_attribute = ProductAttributeFactory(product_class=product_class, name="Size", code="size", type="text")
parent_product = ProductFactory(structure="parent", product_class=product_class, title="Parent Product")
red = ProductAttributeValueFactory(attribute=colour_attribute, product=parent_product, value_text="#ff0000")
small = ProductAttributeValueFactory(attribute=size_attribute, product=parent_product, value_text="Small")
assert str(parent_product) == 'Parent Product'
@pytest.mark.django_db
def test_get_title_returns_string_when_variant_attributes_exist_for_child_products(settings):
settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
product_class = ProductClassFactory(name="Foo")
colour_attribute = ProductAttributeFactory(product_class=product_class, name="Colour", code="colour", type="color")
size_attribute = ProductAttributeFactory(product_class=product_class, name="Size", code="size", type="text")
parent_product = ProductFactory(structure="parent", product_class=product_class)
child_product = ProductFactory(structure="child", parent=parent_product, title = 'Foobar')
red = ProductAttributeValueFactory(attribute=colour_attribute, product=child_product, value_text="#ff0000")
small = ProductAttributeValueFactory(attribute=size_attribute, product=child_product, value_text="Small")
assert child_product.get_title() == 'Foobar (Colour: #ff0000, Size: Small)'
@pytest.mark.django_db
def test_settings_variant_attribute_names_can_be_overriden_trough_setting(settings):
list_of_settings = settings.NSH_VARIANT_PRODUCT_ATTRIBUTE_NAMES = [
"Colour",
"Size",
]
list_of_settings[0] = 'testColour'
list_of_settings[1] = 'testSize'
product_class = ProductClassFactory(name="Foo")
colour_attribute = ProductAttributeFactory(product_class=product_class, name="testColour", code="colour", type="color")
size_attribute = ProductAttributeFactory(product_class=product_class, name="testSize", code="size", type="text")
parent_product = ProductFactory(structure="parent", product_class=product_class, title="Parent Product")
red = ProductAttributeValueFactory(attribute=colour_attribute, product=parent_product, value_text="#ff0000")
small = ProductAttributeValueFactory(attribute=size_attribute, product=parent_product, value_text="Small")
assert parent_product.variant_attribute_summaries == 'testColour: #ff0000, testSize: Small'
Below are the errors I get when I run the tests
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================================================================================== short test summary info ===========================================================================================
FAILED tests/catalogue/test_models.py::test_variant_attribute_summaries_returns_string_when_variant_attributes_exist_for_child_products - AssertionError: assert '' == 'Colour: #ff0000, Size: Small'
FAILED tests/catalogue/test_models.py::test_get_title_returns_string_when_variant_attributes_exist_for_child_products - AssertionError: assert 'Foobar' == 'Foobar (Colo... Size: Small)'
FAILED tests/catalogue/test_models.py::test_settings_variant_attribute_names_can_be_overriden_trough_setting - AssertionError: assert '' == 'testColour: ...stSize: Small'
The code works as expected in the front-end and when the cached-property is removed it works well but I need that property for production purposes, what can I do to allow the tests to run without issues from this? Thank you.
Change
_variant_attribute_summariestovariant_attribute_summariesin your tests as you defined it without a leading underscore in your models...