/
xayoki
/
web4sem
Обзор
Документация
Войти
/
xayoki
/
web4sem
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
shop/models.py
196 строк
9 KB
xayok7
Готовый проект
10 июн 2026, 01:10
10 июн 2026, 01:10
0c2081b
Код
Авторство
О чём код?
from django.db import models from django.contrib.auth.models import AbstractUser from django.utils import timezone from django.urls import reverse from datetime import timedelta from django.db.models import Avg, Count, Sum class AvailableProductManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(stock__gt=0) class User(AbstractUser): ROLE_CHOICES = [ ('client', 'Клиент'), ('admin', 'Администратор'), ] phone = models.CharField(max_length=20, blank=True, null=True, verbose_name="Телефон") address = models.TextField(blank=True, null=True, verbose_name="Адрес доставки") role = models.CharField(max_length=10, choices=ROLE_CHOICES, default='client', verbose_name="Роль") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата регистрации") class Meta: verbose_name = "Пользователь" verbose_name_plural = "Пользователи" def __str__(self): return f"{self.username} ({self.get_role_display()})" class Category(models.Model): name = models.CharField(max_length=100, verbose_name="Название категории") class Meta: verbose_name = "Категория" verbose_name_plural = "Категории" def __str__(self): return self.name class Product(models.Model): category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products', verbose_name="Категория") name = models.CharField(max_length=255, verbose_name="Название изделия") description = models.TextField(verbose_name="Описание") price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Цена") stock = models.PositiveIntegerField(default=0, verbose_name="Остаток на складе") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата добавления") discount_end_date = models.DateTimeField(blank=True, null=True, verbose_name="Конец скидки") image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True, null=True, verbose_name="Изображение") video_url = models.URLField(max_length=200, blank=True, null=True, verbose_name="Ссылка на видеообзор") objects = models.Manager() available = AvailableProductManager() class Meta: verbose_name = "Товар" verbose_name_plural = "Товары" ordering = ['-created_at'] def __str__(self): return self.name def get_absolute_url(self): return reverse('product_detail', kwargs={'pk': self.pk}) def is_new(self): return self.created_at >= timezone.now() - timedelta(days=7) def is_discount_active(self): if self.discount_end_date: return timezone.now() < self.discount_end_date return False def get_price_with_tax(self): return self.price * 1.2 class Supply(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар") quantity = models.PositiveIntegerField(verbose_name="Количество") source = models.CharField(max_length=255, verbose_name="Поставщик / Откуда поступил") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата поступления") class Meta: verbose_name = "Поступление товара" verbose_name_plural = "Поступления товаров" def __str__(self): return f"Поступление: {self.product.name} (+{self.quantity} шт.)" def save(self, *args, **kwargs): is_new = self.pk is None super().save(*args, **kwargs) if is_new: self.product.stock += self.quantity self.product.save() class Order(models.Model): STATUS_CHOICES = [ ('new', 'Новый'), ('paid', 'Оплачен'), ('sent', 'Отправлен'), ('done', 'Завершен'), ] user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Покупатель") total = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итоговая сумма") status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='new', verbose_name="Статус") address = models.TextField(verbose_name="Адрес доставки") comment = models.TextField(blank=True, null=True, verbose_name="Комментарий") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата заказа") products = models.ManyToManyField(Product, through='OrderItem', related_name='orders', verbose_name="Товары в заказе") document = models.FileField(upload_to='orders/docs/', blank=True, null=True, verbose_name="Документ заказа") class Meta: verbose_name = "Заказ" verbose_name_plural = "Заказы" def __str__(self): return f"Заказ №{self.id} от {self.user.username}" def can_cancel(self): return timezone.now() <= self.created_at + timedelta(hours=1) def save(self, *args, **kwargs): if self.pk: old_order = Order.objects.get(pk=self.pk) if old_order.status != 'paid' and self.status == 'paid': for item in self.items.all(): if item.product.stock >= item.quantity: item.product.stock -= item.quantity item.product.save() super().save(*args, **kwargs) class OrderItem(models.Model): order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items', verbose_name="Заказ") product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар") quantity = models.PositiveIntegerField(default=1, verbose_name="Количество") price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Цена на момент заказа") class Meta: verbose_name = "Товар в заказе" verbose_name_plural = "Товары в заказе" def __str__(self): return f"{self.product.name} (x{self.quantity})" class Cart(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, verbose_name="Пользователь") session_id = models.CharField(max_length=255, null=True, blank=True, verbose_name="ID сессии") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") updated_at = models.DateTimeField(auto_now=True, verbose_name="Дата обновления") class Meta: verbose_name = "Корзина" verbose_name_plural = "Корзины" def __str__(self): if self.user: return f"Корзина пользователя {self.user.username}" return f"Анонимная корзина {self.session_id}" class CartItem(models.Model): cart = models.ForeignKey(Cart, on_delete=models.CASCADE, related_name='items', verbose_name="Корзина") product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар") quantity = models.PositiveIntegerField(default=1, verbose_name="Количество") class Meta: verbose_name = "Товар в корзине" verbose_name_plural = "Товары в корзине" def __str__(self): return f"{self.product.name} (x{self.quantity})" class FavoriteItem(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Пользователь") product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата добавления") class Meta: verbose_name = "Избранное" verbose_name_plural = "Избранное" unique_together = ('user', 'product') def __str__(self): return f"{self.user.username} - {self.product.name}" class Review(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='reviews', verbose_name="Товар") user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Автор") rating = models.IntegerField(choices=[(i, i) for i in range(1, 6)], verbose_name="Оценка") comment = models.TextField(verbose_name="Отзыв") created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата") class Meta: verbose_name = "Отзыв" verbose_name_plural = "Отзывы" def __str__(self): return f"Отзыв на {self.product.name} от {self.user.username}"