Fix unique together for translated fields. Fix some manager issues. Add default pagination to views Simplify tag_clog() code
127 lines
5 KiB
Python
127 lines
5 KiB
Python
# -*- coding: utf-8 -*-
|
|
from collections import Counter
|
|
import datetime
|
|
|
|
from django.db import models
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from parler.managers import TranslationManager
|
|
|
|
from .settings import BLOG_TAGCLOUD_MIN, BLOG_TAGCLOUD_MAX
|
|
|
|
|
|
class TaggedFilterItem(object):
|
|
|
|
def tagged(self, other_model=None, queryset=None):
|
|
"""
|
|
Restituisce una queryset di elementi del model taggati,
|
|
o con gli stessi tag di un model o un queryset
|
|
"""
|
|
tags = self._taglist(other_model, queryset)
|
|
return self.get_query_set().filter(taglist__in=tags)
|
|
|
|
def _taglist(self, other_model=None, queryset=None):
|
|
"""
|
|
Restituisce una lista di id di tag comuni al model corrente e al model
|
|
o queryset passati come argomento
|
|
"""
|
|
from taggit.models import TaggedItem
|
|
filtro = None
|
|
if queryset is not None:
|
|
filtro = set()
|
|
for item in queryset.all():
|
|
filtro.update(item.tags.all())
|
|
filtro = set([tag.id for tag in filtro])
|
|
elif other_model is not None:
|
|
filtro = set(TaggedItem.objects.filter(content_type__model=other_model.__name__.lower()).values_list('tag_id', flat=True))
|
|
tags = set(TaggedItem.objects.filter(content_type__model=self.model.__name__.lower()).values_list('tag_id', flat=True))
|
|
if filtro is not None:
|
|
tags = tags.intersection(filtro)
|
|
return list(tags)
|
|
|
|
def tag_list(self, other_model=None, queryset=None):
|
|
"""
|
|
Restituisce un queryset di tag comuni al model corrente e
|
|
al model o queryset passati come argomento
|
|
"""
|
|
from taggit.models import Tag
|
|
return Tag.objects.filter(id__in=self._taglist(other_model, queryset))
|
|
|
|
def tag_list_slug(self, other_model=None, queryset=None):
|
|
qs = self.tag_list(other_model, queryset)
|
|
return qs.values("slug")
|
|
|
|
def tag_cloud(self, other_model=None, queryset=None, published=True):
|
|
from taggit.models import TaggedItem
|
|
tag_ids = self._taglist(other_model, queryset)
|
|
kwargs = {}
|
|
if published:
|
|
kwargs = TaggedItem.bulk_lookup_kwargs(self.model.objects.published())
|
|
kwargs['tag_id__in'] = tag_ids
|
|
counted_tags = dict(TaggedItem.objects
|
|
.filter(**kwargs)
|
|
.values('tag')
|
|
.annotate(count=models.Count('tag'))
|
|
.values_list('tag', 'count'))
|
|
tags = TaggedItem.tag_model().objects.filter(pk__in=counted_tags.keys())
|
|
for tag in tags:
|
|
tag.count = counted_tags[tag.pk]
|
|
return sorted(tags, key=lambda x: -x.count)
|
|
|
|
|
|
class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
|
|
use_for_related_fields = True
|
|
start_date_field = "date_published"
|
|
end_date_field = "date_published_end"
|
|
publish_field = "publish"
|
|
|
|
def published(self, qs=None):
|
|
qs = self.published_future(qs)
|
|
if self.start_date_field:
|
|
return qs.filter(
|
|
**{"%s__lte" % self.start_date_field: datetime.datetime.now()})
|
|
else:
|
|
return qs
|
|
|
|
def published_future(self, qs=None):
|
|
if not qs:
|
|
qs = self.get_query_set().all()
|
|
if self.end_date_field:
|
|
qfilter = (
|
|
models.Q(**{"%s__gte" % self.end_date_field: datetime.datetime.now()})
|
|
| models.Q(**{"%s__isnull" % self.end_date_field: True})
|
|
)
|
|
qs = qs.filter(qfilter)
|
|
return qs.filter(**{self.publish_field: True})
|
|
|
|
def archived(self, qs=None):
|
|
if not qs:
|
|
qs = self.get_query_set().all()
|
|
if self.end_date_field:
|
|
qfilter = (
|
|
models.Q(**{"%s__lte" % self.end_date_field: datetime.datetime.now()})
|
|
| models.Q(**{"%s__isnull" % self.end_date_field: False})
|
|
)
|
|
qs = qs.filter(qfilter)
|
|
return qs.filter(**{self.publish_field: True})
|
|
|
|
def available(self, qs=None):
|
|
if not qs:
|
|
qs = self.get_query_set().all()
|
|
return qs.filter(**{self.publish_field: True})
|
|
|
|
def filter_by_language(self, language):
|
|
qs = self.get_query_set()
|
|
return qs.filter(models.Q(language__isnull=True) | models.Q(language=language))
|
|
|
|
def get_months(self, queryset=None):
|
|
"""Get months with aggregatet count (how much posts is in the month). Results are ordered by date."""
|
|
# done via naive way as django's having tough time while aggregating on date fields
|
|
if not queryset:
|
|
queryset = self.get_query_set()
|
|
dates = queryset.values_list(self.start_date_field, flat=True)
|
|
dates = [(x.year, x.month) for x in dates]
|
|
date_counter = Counter(dates)
|
|
dates = set(dates)
|
|
dates = sorted(dates, reverse=True)
|
|
return [{'date': datetime.date(year=year, month=month, day=1),
|
|
'count': date_counter[year, month]} for year, month in dates]
|