diff --git a/products/models.py b/products/models.py index 910e58b..05fee46 100644 --- a/products/models.py +++ b/products/models.py @@ -3,11 +3,15 @@ from django.urls import reverse_lazy from django.contrib.postgres.fields import HStoreField from django.utils.translation import ugettext_lazy as _ -import mptt +from mptt import ( + models as mptt_models, + managers as mptt_managers, + register +) from mptt.models import MPTTModel, TreeForeignKey from autoslug import AutoSlugField -from core.models import AbstractStatusModel, AbstractDateTimeModel +from core.models import AbstractStatusModel, AbstractDateTimeModel, STATUS_ACTIVE, STATUS_DELETED class ProductAttribute(AbstractStatusModel): @@ -20,8 +24,9 @@ class ProductAttribute(AbstractStatusModel): class Meta: ordering = ('slug',) - verbose_name = _('Product attribute') - verbose_name_plural = _('Product attributes') + verbose_name = _('Аттрибут продукта') + verbose_name_plural = _('Аттрибуты продукта') + class Manufacturer(AbstractStatusModel): name = models.CharField(max_length=64, blank=True, null=True, default=None) @@ -34,31 +39,39 @@ class Manufacturer(AbstractStatusModel): def get_absolute_url(self): return reverse_lazy('products:manufacturer', kwargs={'producer_slug': self.slug, 'path': ''}) - #@TODO: tranlsate into english and use traslation + # @TODO: tranlsate into english and use traslation class Meta: verbose_name = _('Производитель') verbose_name_plural = _('Производители') +class ProductCategoryManager(mptt_managers.TreeManager): + def get_root_categories(self): + return self.get_queryset().all() + + class ProductCategory(MPTTModel, AbstractDateTimeModel): name = models.CharField(db_index=True, unique=True, max_length=64, blank=True, null=True, default=None) slug = AutoSlugField(populate_from='name') parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') image = models.ImageField(upload_to='categories', blank=True, verbose_name="image of category") + objects = ProductCategoryManager() + def __str__(self): return self.name + # @TODO: tranlsate into english and use traslation class Meta: - verbose_name = 'Product\'s category' - verbose_name_plural = 'Product\'s categories' + verbose_name = _("Категория") + verbose_name_plural = _("Категории") ordering = ('tree_id', 'level') class MPTTMeta: order_insertion_by = ['name'] -mptt.register(ProductCategory, order_insertion_py=['name']) +register(ProductCategory, order_insertion_py=['name']) class Product(AbstractStatusModel): @@ -67,7 +80,6 @@ class Product(AbstractStatusModel): price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00) description = models.TextField(db_index=True, blank=True, null=True, default=None) manufacturer = models.ForeignKey(Manufacturer, on_delete=models.PROTECT) - image = models.ImageField(upload_to='products', blank=True, verbose_name="image of products") category = models.ForeignKey(ProductCategory, on_delete=models.SET_NULL, blank=True, null=True, default=None) attributes = models.ManyToManyField(ProductAttribute, blank=True) discount_policy = HStoreField(blank=True, null=True, default={}) @@ -83,8 +95,8 @@ class Product(AbstractStatusModel): indexes = [ models.Index(fields=['id', 'slug']) ] - verbose_name = _('Product') - verbose_name_plural = _('Products') + verbose_name = _('Продукт') + verbose_name_plural = _('Продукты') @@ -114,6 +126,40 @@ class ProductAttributeValue(AbstractDateTimeModel): verbose_name = 'Product attribute value' verbose_name_plural = 'Product attribute values' + +# ----------------- PRODUCT IMAGE STATUS LIST ------------------ + +PRODUCT_IMAGE_STATUS_CHOICES = ( + (STATUS_ACTIVE, _('Активный')), + (STATUS_DELETED, _('Удален')), +) + +PRODUCT_IMAGE_DEFAULT_STATUS = STATUS_ACTIVE + + +class ProductImage(AbstractStatusModel): + def get_file_path(self, filename): + return "products/attachments/{product}/{filename}".format(**{ + 'product': self.product.id, + 'filename': filename + }) + + product = models.ForeignKey(Product, on_delete=models.CASCADE) + status = models.SmallIntegerField(_('Статус'), default=PRODUCT_IMAGE_DEFAULT_STATUS, + choices=PRODUCT_IMAGE_STATUS_CHOICES) + filename = models.CharField(_('Имя файла'), max_length=255) + image = models.FileField(_('Изображение'), upload_to=get_file_path, max_length=500) + is_default = models.BooleanField(_('По умолчанию'), default=False) + + @classmethod + def create(cls, request, file): + product_image = cls(request=request, file=file, filename=file.name) + return product_image + + class Meta: + verbose_name = _('Изображение продукта') + verbose_name_plural = _('Изображения продуктов') + # class Offer(models.Model): # name = models.CharField(max_length=64, blank=True, null=True, default=None) # slug = AutoSlugField(populate_from='name')