Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from django.db import models
- from django.db.models import F, Q
- from django.db.models.functions import Greatest
- from django.contrib.auth.models import AbstractUser
- from django.utils import timezone
- # Create your models here.
- # Код отформатирован в PyCharm
- class ProductManager(models.Manager):
- def get_ordered_products(self, start_price=1000, end_price=10000):
- now = timezone.now()
- """
- Проверка что скидка активна
- """
- brand_discount = Q(Q(brand__discount__date_end__gte=now) & Q(brand__discount__date_start__lte=now))
- category_discount = Q(Q(category__discount__date_end__gte=now) & Q(category__discount__date_start__lte=now))
- discount = Q(Q(discount__date_end__gte=now) & Q(discount__date_start__lte=now))
- """
- Брать продукты у которых вообще нет скидки
- """
- no_discount = Q(Q(brand__discount__isnull=True) & Q(category__discount__isnull=True) & Q(discount__isnull=True))
- """
- Аннотирование запроса, всё в одном словаре
- """
- annotations = {
- 'brand_discount': F('brand__discount__discount'), # Скидка по бренду
- 'category_discount': F('category__discount__discount'),# Скидка по категории
- 'self_discount': F('discount__discount'), # Собственная скидка
- # Полная цена вычесляется от собственной цены - максимальная скидка
- # 0 нужен для того, что бы в случае отсутсвия скидок, из цены на вычетался None
- 'full_price': F('price') - Greatest(0, 'brand_discount', 'category_discount', 'self_discount')
- }
- return self.get_queryset().filter(brand_discount | category_discount | discount | no_discount) \
- .annotate(**annotations) \
- .filter(full_price__gte=start_price, full_price__lte=end_price) \
- .order_by('full_price')
- class Discount(models.Model):
- date_start = models.DateTimeField(verbose_name='Начало действия скидки')
- date_end = models.DateTimeField(verbose_name='Конец действия скидки')
- discount = models.DecimalField(verbose_name='Скидка', max_digits=10, decimal_places=2)
- class Meta:
- verbose_name = 'Скидка'
- verbose_name_plural = 'Скидки'
- def __repr__(self):
- return f'<{self.discount} {self.date_start} {self.date_end}>'
- class Customer(AbstractUser):
- discount = models.ForeignKey(Discount, verbose_name='Скидка', null=True, blank=True, on_delete=models.SET_NULL)
- class Meta:
- verbose_name = 'Пользователь'
- verbose_name_plural = 'Пользователи'
- def __str__(self):
- return self.email
- class Category(models.Model):
- name = models.CharField('Группа товара', max_length=64)
- discount = models.ForeignKey(Discount, verbose_name='Скидка', null=True, blank=True, on_delete=models.SET_NULL)
- class Meta:
- verbose_name_plural = 'Категории'
- verbose_name = 'Категория'
- def __repr__(self):
- return f'<{self.name}>'
- class Brand(models.Model):
- name = models.CharField('Бренд', max_length=64)
- discount = models.ForeignKey(Discount, verbose_name='Скидка', null=True, blank=True, on_delete=models.SET_NULL)
- class Meta:
- verbose_name_plural = 'Бренды'
- verbose_name = 'Бренд'
- def __repr__(self):
- return f'<{self.name}>'
- class Product(models.Model):
- category = models.ForeignKey(Category, verbose_name='Группа', null=True, blank=True,
- on_delete=models.SET_NULL, related_name='products')
- brand = models.ForeignKey(Brand, verbose_name='Бренд', related_name='products',
- null=True, blank=True, on_delete=models.SET_NULL)
- discount = models.ForeignKey(Discount, verbose_name='Скидка', null=True, blank=True,
- on_delete=models.SET_NULL, related_name='products')
- name = models.CharField('Название товара', max_length=128)
- price = models.DecimalField('Стоимость единицы, руб.', max_digits=10, decimal_places=2)
- objects = ProductManager()
- class Meta:
- verbose_name_plural = 'Товары'
- verbose_name = 'Товар'
- def __repr__(self):
- return f'<{self.name} {self.price}>'
Add Comment
Please, Sign In to add comment