123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- from django.db import models
- from django.contrib.auth.models import AbstractUser
- from django.db.models.signals import post_save
- from .utilities import get_timestamp_path, send_new_comment_notification
- class AdvUser(AbstractUser):
- is_activated = models.BooleanField(default=True, db_index=True, verbose_name='Прошел активацию?')
- send_messages = models.BooleanField(default=True, verbose_name='Оповещение на email о новых комментариях?')
-
- # При удалении пользователя удаляем и его объявления
- def delete(self, *args, **kwargs):
- for ad in self.ad_set.all():
- ad.delete()
- super().delete(*args, **kwargs)
- class Meta(AbstractUser.Meta):
- pass
- class Rubric(models.Model):
- # Базовая модель, в которой хранятся и главные рубрики, и подрубрики
- name = models.CharField(max_length=30, db_index=True, unique=True, verbose_name='Название')
- order = models.SmallIntegerField(default=0, db_index=True, verbose_name='Порядок следования')
- super_rubric = models.ForeignKey('SuperRubric', on_delete=models.PROTECT, null=True, blank=True, verbose_name='Главная рубрика')
- class SuperRubricManager(models.Manager):
- # Обработка только главных рубрик
- def get_queryset(self):
- return super().get_queryset().filter(super_rubric__isnull=True)
- class SuperRubric(Rubric):
- objects = SuperRubricManager()
-
- def __str__(self):
- # Метод генерит строковое название Главной рубрики
- return self.name
- class Meta:
- proxy = True
- ordering = ('order', 'name')
- verbose_name = 'Главная рубрика'
- verbose_name_plural = 'Главные рубрики'
- class SubRubricManager(models.Manager):
- def get_queryset(self):
- return super().get_queryset().filter(super_rubric__isnull=False)
- class SubRubric(Rubric):
- objects = SubRubricManager()
-
- def __str__(self):
- return '%s - %s' % (self.super_rubric.name, self.name)
- class Meta:
- proxy = True
- ordering = ('super_rubric__order', 'super_rubric__name', 'order', 'name')
- verbose_name = 'Подрубрика'
- verbose_name_plural = 'Подрубрики'
- # Класс самих объявлений
- class Ad(models.Model):
- rubric = models.ForeignKey(SubRubric, on_delete=models.PROTECT, verbose_name='Рубрика') # Запрет каскадного удаления
- title = models.CharField(max_length=40, verbose_name='Товар')
- content = models.TextField(verbose_name='Описание')
- price = models.FloatField(default=0, verbose_name='Цена')
- contacts = models.TextField(verbose_name='Контакты')
- image = models.ImageField(blank=True, upload_to=get_timestamp_path, verbose_name='Изображение')
- # разрешаем каскадное удаление. Т.е. при удалении объявления будут уничтожены все относящиеся к нему Дополнительные Изображения.
- # Это действие выполнит не Django, а СУБД. Т.е. физического удаления с диска файлов Изображений не произойдет.
- author = models.ForeignKey(AdvUser, on_delete=models.CASCADE, verbose_name='Автор объявления')
- is_active = models.BooleanField(default=True, db_index=True, verbose_name='Выводить в списке объявлений?')
- created_at = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Опубликовано')
- # Перед удалением текущей записи мы перебираем и вызовом метода delete() удаляем все связанные Дополнительные Изображения.
- # При вызове метода delete() возникает сигнал post_delete, обрабатываемый приложением django_cleanup, которое удалит файлы Изображений физически с диска.
- def delete(self, *args, **kwargs):
- for ai in self.additionalimage_set.all():
- ai.delete()
- super().delete(*args, **kwargs)
- class Meta:
- verbose_name_plural = 'Объявления'
- verbose_name = 'Объявление'
- ordering = ['-created_at']
- # Класс Дополнительных изображений
- class AdditionalImage(models.Model):
- # Объявление, к которому относится Изображение
- ad = models.ForeignKey(Ad, on_delete=models.CASCADE, verbose_name='Объявление')
- image = models.ImageField(upload_to=get_timestamp_path, verbose_name='Изображение')
- class Meta:
- verbose_name_plural = 'Дополнительные изображения'
- verbose_name = 'Дополнительное изображение'
- #Класс Комментариев
- class Comment(models.Model):
- ad = models.ForeignKey(Ad, on_delete=models.CASCADE, verbose_name='Объявление')
- author = models.CharField(max_length=30, verbose_name='Автор')
- content = models.TextField(verbose_name='Комментарий')
- is_active = models.BooleanField(default=True, db_index=True, verbose_name='Выводить на экран?')
- created_at = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Опубликован')
- class Meta:
- verbose_name_plural = 'Комментарии'
- verbose_name = 'Комментарий'
- ordering = ['created_at'] # Сортировка по увеличению временной отметки, т.е. более старые комментарии будут располагаться в начале списка, а более новые - в конце.
- # Привяжем к сигналу post_save обработчик, вызывающий функцию send_new_comment_notification
- # после добавления комментария
- def post_save_dispatcher(sender, **kwargs):
- author = kwargs['instance'].ad.author
- if kwargs['created'] and author.send_messages:
- send_new_comment_notification(kwargs['instance'])
- post_save.connect(post_save_dispatcher, sender=Comment)
|