from django.contrib.postgres.fields import JSONField from django.contrib.postgres.fields.jsonb import KeyTextTransform from django.db import models from django.utils.translation import gettext_lazy as _ from utils.models import ProjectBaseMixin, BaseAttributes class NewsType(models.Model): """NewsType model.""" name = models.CharField(_('name'), max_length=250) class NewsManager(models.Manager): """Manager for model News""" def annotate_localized_fields(self, locale): """Return queryset by locale""" prefix = 'trans' # Prepare fields to localization (only JSONField can be localized) fields = [field.name for field in self.model._meta.fields if isinstance(field, JSONField)] # Check filters to check if field has localization filters = {f'{field}__has_key': locale for field in fields} # Filter QuerySet by prepared filters queryset = self.filter(**filters) # Prepare field for annotator localized_fields = {f'{field}_{prefix}': KeyTextTransform(f'{locale}', field) for field in fields} # Annotate them for _ in fields: queryset = queryset.annotate(**localized_fields) return queryset class NewsQuerySet(models.QuerySet): """QuerySet for model News""" def by_type(self, news_type): """Filter News by type""" return self.filter(news_type__name=news_type) class News(BaseAttributes): """News model.""" news_type = models.ForeignKey( NewsType, verbose_name=_('news type'), on_delete=models.CASCADE) title = JSONField( _('title'), null=True, blank=True, default=None, help_text='{"en":"some text"}') subtitle = JSONField( _('subtitle'), null=True, blank=True, default=None, help_text='{"en":"some text"}' ) description = JSONField( _('subtitle'), null=True, blank=True, default=None, help_text='{"en":"some text"}' ) start = models.DateTimeField(_('start')) end = models.DateTimeField(_('end')) playlist = models.IntegerField(_('playlist')) address = models.ForeignKey( 'location.Address', verbose_name=_('address'), blank=True, null=True, default=None, on_delete=models.CASCADE) # TODO: metadata_keys - описание ключей для динамического построения полей метаданных # TODO: metadata_values - Описание значений для динамических полей из MetadataKeys objects = NewsManager.from_queryset(NewsQuerySet)() class Meta: verbose_name = _('news') verbose_name_plural = _('news') def __str__(self): return f'news: {self.id}'