modified params assignment

main^2
mtyton 2023-08-15 21:00:16 +02:00
commit 4ba1f975fe
10 zmienionych plików z 72 dodań i 93 usunięć

1
.gitignore vendored
Wyświetl plik

@ -143,3 +143,4 @@ artel/static/
# media # media
artel/media/* artel/media/*
artel/store/data/*

Wyświetl plik

@ -5,7 +5,7 @@ from django.db.models import Model
from store.models import ( from store.models import (
ProductTemplate, ProductTemplate,
ProductTemplateParam, ProductTemplateParamValue,
Product, Product,
PaymentMethod, PaymentMethod,
DeliveryMethod DeliveryMethod
@ -71,11 +71,16 @@ class ButtonToggleSelect(forms.RadioSelect):
class ProductTemplateConfigForm(forms.Form): class ProductTemplateConfigForm(forms.Form):
def _create_dynamic_fields(self, template: ProductTemplate): def _create_dynamic_fields(self, template: ProductTemplate):
category_params = template.category.category_params.all() template_params = template.template_params.all()
for param in category_params: for param in template_params:
queryset = ProductTemplateParamValue.objects.filter(param=param)
if queryset.count() >= 4:
widget = forms.Select(attrs={"class": "form-select"})
else:
widget = ButtonToggleSelect(attrs={"class": "btn-group btn-group-toggle"})
self.fields[param.key] = forms.ModelChoiceField( self.fields[param.key] = forms.ModelChoiceField(
queryset=ProductTemplateParam.objects.filter(param=param), queryset=queryset,
widget=ButtonToggleSelect(attrs={"class": "btn-group btn-group-toggle"}), widget=widget,
) )
def __init__( def __init__(

Wyświetl plik

@ -1,12 +1,14 @@
import logging import logging
import time
import requests import requests
import pandas as pd import pandas as pd
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.conf import settings
from store.models import ( from store.models import (
ProductTemplate, ProductTemplate,
ProductTemplateParam, ProductTemplateParam,
ProductTemplateParamValue,
Product, Product,
ProductImage ProductImage
) )
@ -29,15 +31,24 @@ class TemplateLoader(BaseLoader):
class ProductLoader(BaseLoader): class ProductLoader(BaseLoader):
def _clear(self):
Product.objects.all().delete()
def __init__(self, path, param_names, clear=False):
super().__init__(path)
self.param_names = param_names
if clear:
self._clear()
def _get_images(self, row) -> list[ContentFile]: def _get_images(self, row) -> list[ContentFile]:
urls = row["images"] url = row["images"]
images = [] images = []
for url in urls: response = requests.get(
response = requests.get(url, stream=True) url+"/preview", stream=True
if response.status_code == 200: )
data = response.raw if response.status_code == 200:
file_name = url.split("/")[-1] data = response.content
image = ContentFile(data, name=file_name) image = ContentFile(data, name=row["template"])
images.append(image) images.append(image)
return images return images
@ -47,10 +58,11 @@ class ProductLoader(BaseLoader):
name = row["name"] name = row["name"]
available = bool(row["available"]) available = bool(row["available"])
params = [] params = []
for param in row["params"]: for key in self.param_names:
key, value = param value = row[key]
param = ProductTemplateParam.objects.get(param__key=key, value=value) param, _ = ProductTemplateParam.objects.get_or_create(key=key, template=template)
params.append(param) param_value, _ = ProductTemplateParamValue.objects.get_or_create(param=param, value=value)
params.append(param_value)
product = Product.objects.get_or_create_by_params(template=template, params=params) product = Product.objects.get_or_create_by_params(template=template, params=params)
product.price = price product.price = price
product.name = name product.name = name
@ -66,6 +78,7 @@ class ProductLoader(BaseLoader):
data = self.load_data() data = self.load_data()
products = [] products = []
for _, row in data.iterrows(): for _, row in data.iterrows():
time.sleep(5)
try: try:
product = self._process_row(row) product = self._process_row(row)
except Exception as e: except Exception as e:

Wyświetl plik

@ -9,5 +9,5 @@ class Command(BaseCommand):
help = "Load products from csv file" help = "Load products from csv file"
def handle(self, *args, **options): def handle(self, *args, **options):
loader = ProductLoader(settings.PRODUCTS_CSV_PATH) loader = ProductLoader(settings.PRODUCTS_CSV_PATH, ["mocowanie", "format", "wykonanie"], True)
loader.process() loader.process()

Wyświetl plik

@ -90,8 +90,7 @@ class ProductCategory(ClusterableModel):
return self.name return self.name
panels = [ panels = [
FieldPanel("name"), FieldPanel("name")
InlinePanel("category_params")
] ]
@ -122,6 +121,7 @@ class ProductTemplate(ClusterableModel):
FieldPanel('description'), FieldPanel('description'),
InlinePanel("template_images", label="Template Images"), InlinePanel("template_images", label="Template Images"),
FieldPanel("tags"), FieldPanel("tags"),
InlinePanel("template_params")
] ]

Wyświetl plik

@ -10,19 +10,3 @@
{% endfor %} {% endfor %}
</div> </div>
{% endwith %} {% endwith %}
<!--
{% with id=widget.attrs.id %}
<div{% if id %} id="{{ id }}"{% endif %}
{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}
>
{% for group, options, index in widget.optgroups %}
{% if group %}
<div><label>{{ group }}</label>{% endif %}{% for option in options %}<div>
{% include option.template_name with widget=option %}</div>{% endfor %}{% if group %}
</div>
{% endif %}
{% endfor %}
</div>
{% endwith %}
-->

Wyświetl plik

@ -74,7 +74,7 @@ class ProductParamFactory(DjangoModelFactory):
model = 'store.ProductParam' model = 'store.ProductParam'
product = SubFactory(ProductFactory) product = SubFactory(ProductFactory)
param = SubFactory(ProductCategoryParamFactory) param = SubFactory(ProductTemplateParamValueFactory)
class PaymentMethodFactory(DjangoModelFactory): class PaymentMethodFactory(DjangoModelFactory):

Wyświetl plik

@ -10,23 +10,21 @@ class TestProductLoader(TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.category = factories.ProductCategoryFactory() self.category = factories.ProductCategoryFactory()
self.template = factories.ProductTemplateFactory(category=self.category) self.template = factories.ProductTemplateFactory(category=self.category)
self.category_params = [factories.ProductTemplateParamFactory(category=self.category) for _ in range(3)] self.template_params = [factories.ProductTemplateParamFactory(template=self.template) for _ in range(3)]
self.category_param_values = [factories.ProductTemplateParamValueFactory(param=param) for param in self.category_params] self.templat_params_values = [factories.ProductTemplateParamValueFactory(param=param) for param in self.template_params]
def test_load_products_single_product_success(self): def test_load_products_single_product_success(self):
fake_df = pd.DataFrame({ fake_df = pd.DataFrame({
"template": [self.template.code], "template": [self.template.code],
"price": [10.0], "price": str(10.0),
"name": ["Test product"], "name": ["Test product"],
"available": [True], "available": [True],
"params": [[ self.template_params[0].key: self.templat_params_values[0].value,
(self.category_params[0].key, self.category_param_values[0].value), self.template_params[1].key: self.templat_params_values[1].value,
(self.category_params[1].key, self.category_param_values[1].value), self.template_params[2].key: self.templat_params_values[2].value
(self.category_params[2].key, self.category_param_values[2].value),
]]
}) })
with patch("store.loader.BaseLoader.load_data", return_value=fake_df): with patch("store.loader.BaseLoader.load_data", return_value=fake_df):
loader = ProductLoader("fake_path") loader = ProductLoader("fake_path", [p.key for p in self.template_params])
loader.process() loader.process()
self.assertEqual(self.template.products.count(), 1) self.assertEqual(self.template.products.count(), 1)
@ -42,14 +40,12 @@ class TestProductLoader(TestCase):
"price": ["FASDSADQAW"], "price": ["FASDSADQAW"],
"name": ["Test product"], "name": ["Test product"],
"available": [True], "available": [True],
"params": [[ self.template_params[0].key: self.templat_params_values[0].value,
(self.category_params[0].key, self.category_param_values[0].value), self.template_params[1].key: self.templat_params_values[1].value,
(self.category_params[1].key, self.category_param_values[1].value), self.template_params[2].key: self.templat_params_values[2].value
(self.category_params[2].key, self.category_param_values[2].value),
]]
}) })
with patch("store.loader.BaseLoader.load_data", return_value=fake_df): with patch("store.loader.BaseLoader.load_data", return_value=fake_df):
loader = ProductLoader("fake_path") loader = ProductLoader("fake_path", [p.key for p in self.template_params])
loader.process() loader.process()
self.assertEqual(self.template.products.count(), 0) self.assertEqual(self.template.products.count(), 0)
@ -59,39 +55,17 @@ class TestProductLoader(TestCase):
def test_load_no_existing_template_code_failure(self, mock_logger): def test_load_no_existing_template_code_failure(self, mock_logger):
fake_df = pd.DataFrame({ fake_df = pd.DataFrame({
"template": ["NOTEEXISTINGTEMPLATE"], "template": ["NOTEEXISTINGTEMPLATE"],
"price": [10.0], "price": str(10.0),
"name": ["Test product"], "name": ["Test product"],
"available": [True], "available": [True],
"params": [[ self.template_params[0].key: self.templat_params_values[0].value,
(self.category_params[0].key, self.category_param_values[0].value), self.template_params[1].key: self.templat_params_values[1].value,
(self.category_params[1].key, self.category_param_values[1].value), self.template_params[2].key: self.templat_params_values[2].value
(self.category_params[2].key, self.category_param_values[2].value),
]]
}) })
with patch("store.loader.BaseLoader.load_data", return_value=fake_df): with patch("store.loader.BaseLoader.load_data", return_value=fake_df):
loader = ProductLoader("fake_path") loader = ProductLoader("fake_path", [p.key for p in self.template_params])
loader.process() loader.process()
self.assertEqual(self.template.products.count(), 0) self.assertEqual(self.template.products.count(), 0)
mock_logger.exception.assert_called_with("ProductTemplate matching query does not exist.") mock_logger.exception.assert_called_with("ProductTemplate matching query does not exist.")
@patch("store.loader.logger")
def test_not_existing_params_key_value_pairs_failure(self, mock_logger):
fake_df = pd.DataFrame({
"template": [self.template.code],
"price": [10.0],
"name": ["Test product"],
"available": [True],
"params": [[
(self.category_params[0].key, self.category_param_values[2].value),
(self.category_params[1].key, self.category_param_values[0].value),
(self.category_params[2].key, self.category_param_values[1].value),
]]
})
with patch("store.loader.BaseLoader.load_data", return_value=fake_df):
loader = ProductLoader("fake_path")
loader.process()
self.assertEqual(self.template.products.count(), 0)
mock_logger.exception.assert_called_with("ProductTemplateyParamValue matching query does not exist.")

Wyświetl plik

@ -15,8 +15,9 @@ class ProductCategoryParamTestCase(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.category = factories.ProductCategoryFactory() self.category = factories.ProductCategoryFactory()
self.param = factories.ProductCategoryParamFactory( self.template = factories.ProductTemplateFactory(category=self.category)
category=self.category, self.param = factories.ProductTemplateParamFactory(
template=self.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
@ -44,11 +45,12 @@ class ProductTemplateParamValueTestCase(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.category = factories.ProductCategoryFactory() self.category = factories.ProductCategoryFactory()
self.template = factories.ProductTemplateFactory(category=self.category)
def test_get_value_success(self): def test_get_value_success(self):
param = factories.ProductCategoryParamFactory( param = factories.ProductTemplateParamFactory(
category=self.category, template=self.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
@ -57,8 +59,8 @@ class ProductTemplateParamValueTestCase(TestCase):
self.assertEqual(proper_value, 23) self.assertEqual(proper_value, 23)
def test_get_value_failure_wrong_value(self): def test_get_value_failure_wrong_value(self):
param = factories.ProductCategoryParamFactory( param = factories.ProductTemplateParamFactory(
category=self.category, template=self.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
@ -69,10 +71,10 @@ class ProductTemplateParamValueTestCase(TestCase):
class ProductTestCase(TestCase): class ProductTestCase(TestCase):
def test_category_params_one_value_success(self): def test_template_params_one_value_success(self):
product = factories.ProductFactory() product = factories.ProductFactory()
param = factories.ProductCategoryParamFactory( param = factories.ProductTemplateParamFactory(
category=product.template.category, template=product.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )
@ -83,10 +85,10 @@ class ProductTestCase(TestCase):
self.assertEqual(product.params.count(), 1) self.assertEqual(product.params.count(), 1)
self.assertEqual(product.params.first().get_value(), 23) self.assertEqual(product.params.first().get_value(), 23)
def test_category_params_multiple_values_failure(self): def test_template_params_multiple_values_failure(self):
product = factories.ProductFactory() product = factories.ProductFactory()
param = factories.ProductCategoryParamFactory( param = factories.ProductTemplateParamFactory(
category=product.template.category, template=product.template,
param_type="int", param_type="int",
key="test_param" key="test_param"
) )

Wyświetl plik

@ -22,13 +22,13 @@ class ConfigureProductViewTestCase(TestCase):
self.product_template = ProductTemplateFactory(category=self.category) self.product_template = ProductTemplateFactory(category=self.category)
# create template params and values for those params # create template params and values for those params
self.param1 = ProductTemplateParam.objects.create( self.param1 = ProductTemplateParam.objects.create(
key="Mocowanie", category=self.category, key="Mocowanie", template=self.product_template,
param_type=TemplateParamValueChoices.STRING param_type=TemplateParamValueChoices.STRING
) )
self.param1_value1 = ProductTemplateParamValueFactory(param=self.param1) self.param1_value1 = ProductTemplateParamValueFactory(param=self.param1)
self.param1_value2 = ProductTemplateParamValueFactory(param=self.param1) self.param1_value2 = ProductTemplateParamValueFactory(param=self.param1)
self.param2 = ProductTemplateParam.objects.create( self.param2 = ProductTemplateParam.objects.create(
key="Format", category=self.category, key="Format", template=self.product_template,
param_type=TemplateParamValueChoices.STRING param_type=TemplateParamValueChoices.STRING
) )
self.param2_value1 = ProductTemplateParamValueFactory(param=self.param2) self.param2_value1 = ProductTemplateParamValueFactory(param=self.param2)