# -*- coding: utf-8 -*- import copy import calendar as python_calendar from itertools import chain from pytils.dt import ru_strftime import datetime from datetime import date from dateutil.relativedelta import relativedelta from django.conf import settings from django.db.models import Q from django.utils.translation import ugettext as _ from django.utils.translation import get_language from django.utils.safestring import mark_safe from django.core.urlresolvers import reverse from django.http import QueryDict from hvad.utils import get_translation, set_cached_translation, get_cached_translation from functions.translate import fill_with_signal from service.models import Service from photologue.models import Gallery class ExpoMixin(object): def get_top_link(self): if self.top: return self.top.link.get_click_link() else: return self.get_permanent_url() def get_logo(self): logo = self.files.filter(purpose='logo') if logo: return logo[0] return self.logo def get_preview(self): preview = self.files.filter(purpose='preview') if preview: return preview[0] return preview def get_photos(self): photos = self.files.filter(purpose='photo') return photos def get_dates(data_begin, data_end, v2=False): _v1 = _(u'c {start} по {end}') _v2 = _(u'{start}-{end}') lang = get_language() if data_end and data_begin: delta = data_end - data_begin if delta.days > 28 and data_end.month == data_begin.month: return data_begin.strftime('%B') elif delta.days < 1: if lang == 'ru': return ru_strftime("%d %B %Y", date=data_begin, inflected=True) return data_begin if data_begin.month != data_end.month: if lang == 'ru': start = ru_strftime("%d %B", date=data_begin, inflected=True) else: start = u'{month} {day}'.format( month=data_begin.strftime('%B'), day=data_begin.day) else: start = data_begin.day if lang == 'ru': end = ru_strftime("%d %B", date=data_end, inflected=True) else: end = u'{month} {day}'.format( month=data_end.strftime('%B'), day=data_end.day) if not v2: return _v1.format(start=start, end=end) return _v2.format(start=start, end=end) if lang == 'ru': return ru_strftime("%d %B %Y", date=data_begin, inflected=True) return data_begin class EventMixin(object): def default_description_context(self): lang = get_language() booking_url_params = QueryDict('', mutable=True) booking_url_params.update({ 'aid': 333667, 'city': self.city_id, 'do_availability_check': 'on', 'label': '{}_search'.format(self.event_type), 'lang': lang, 'checkin_monthday': self.data_begin.strftime('%d'), 'checkin_year_month': self.data_begin.strftime('%Y-%m'), 'checkout_monthday': self.data_end.strftime('%d'), 'checkout_year_month': self.data_end.strftime('%Y-%m'), }) booking_url = 'http://www.booking.com/searchresults.html?' + booking_url_params.urlencode() try: theme_name = self.theme.language().all()[0] except IndexError: theme_name = '' ctx = { 'name': self.name, 'short_descr': self.main_title, 'dates': self.get_dates, 'country': self.country.name if self.country else '', 'city': self.city.name if self.city else '', 'place': self.get_event_place_name(), 'place_url': self.place.url if self.place else None, 'theme': theme_name, 'tags': ', '.join([t.name for t in self.tag.language().all()]), 'booking_url': booking_url, } return ctx def get_nearest_events_incl(self, _qs, tags, themes, exclude=None): now = datetime.datetime.now() month = now + relativedelta(months=1) month2 = now + relativedelta(months=2) exclude_pks = exclude or set([self.pk]) events_m2 = [] events_m = [] events = [] for params in [{'tag__in': tags}, {'theme__in': themes}]: qs = _qs.filter(**params).order_by('data_begin').distinct() events_m2.extend(list(qs.filter(data_begin__gte=month2).exclude(pk__in=exclude_pks)[:3])) exclude_pks.update([x.pk for x in events_m2]) events_m.extend(list(qs.filter(data_begin__gte=month).exclude(pk__in=exclude_pks)[:3])) exclude_pks.update([x.pk for x in events_m]) events.extend(list(qs.filter(data_begin__gte=now).exclude(pk__in=exclude_pks)[:3])) exclude_pks.update([x.pk for x in events]) return (list( sorted(list(chain(*zip(*[x for x in [events_m2, events_m, events] if x])))[:3], key=lambda x: x.data_begin)), exclude_pks) def get_nearest_events(self): if getattr(self, '_nearest_events', None) is None or self._nearest_events == []: model = self.__class__ result = [] tags = list(self.tag.all().values_list('pk', flat=True)) themes = list(self.theme.all().values_list('pk', flat=True)) qs = model.objects.language().filter(country_id=self.country_id) result, exclude = self.get_nearest_events_incl(qs, tags, themes) if len(result) > 3: qs = model.objects.language() r, e = self.get_nearest_events_incl(qs, tags, themes, exclude) result += r self._nearest_events = result[:3] return self._nearest_events def get_recommend_expos_incl(self, _qs, tags, themes, exclude=None): now = datetime.datetime.now() month = now + relativedelta(months=1) month2 = now + relativedelta(months=2) exclude_pks = exclude or set([self.pk]) events_m2 = [] events_m = [] events = [] for params in [{'tag__in': tags}, {'theme__in': themes}]: qs = _qs.filter(**params).order_by('data_begin').distinct() events_m2.extend(list(qs.filter(data_begin__gte=month2).exclude(pk__in=exclude_pks)[3:5])) exclude_pks.update([x.pk for x in events_m2]) events_m.extend(list(qs.filter(data_begin__gte=month).exclude(pk__in=exclude_pks)[3:5])) exclude_pks.update([x.pk for x in events_m]) events.extend(list(qs.filter(data_begin__gte=now).exclude(pk__in=exclude_pks)[3:5])) exclude_pks.update([x.pk for x in events]) return (list(sorted(list(chain(*zip(*[x for x in [events_m2, events_m, events] if x])))[3:5], key=lambda x: x.data_begin)), exclude_pks) def get_recommend_expos(self): if getattr(self, '_recommend_expos', None) is None or self._recommend_expos == []: model = self.__class__ result = [] tags = list(self.tag.all().values_list('pk', flat=True)) themes = list(self.theme.all().values_list('pk', flat=True)) top_expos = list( model.objects.filter( top__isnull=False, theme__in=themes, top__fr__lte=date.today(), top__to__gte=date.today() ).order_by('?') ) paid_expos = list( model.objects.filter( paid_new__isnull=False, theme__in=themes, top__fr__lte=date.today(), top__to__gte=date.today() ).order_by('?') ) qs = model.objects.language().filter(country_id=self.country_id) result, exclude = self.get_recommend_expos_incl(qs, tags, themes) if len(result) > 5: qs = model.objects.language() r, e = self.get_recommend_expos_incl(qs, tags, themes, exclude) result += r result = list(set(top_expos + paid_expos + result)) if len(result) < 5: self._recommend_expos = result[:2] else: self._recommend_expos = result[3:5] return self._recommend_expos def get_nearest_events_url(self): url_params = QueryDict('', mutable=True) url_params.update({ 'date_from': datetime.datetime.now().strftime('%d.%m.%Y'), 'event_type': 1 if self.event_type == 'expo' else 2, }) url_params.setlist('tag', self.tag.all().values_list('pk', flat=True)) url_params.setlist('theme', self.theme.all().values_list('pk', flat=True)) return mark_safe(reverse('events:main') + '?' + url_params.urlencode()) def get_currency_html(self): cur = self.currency currency_codes = {'EUR':'€', 'USD':'$', 'RUB':'руб.'} code = currency_codes.get(cur) if code: return code return cur @property def get_dates(self): return get_dates(self.data_begin, self.data_end) @property def get_dates_v2(self): return get_dates(self.data_begin, self.data_end, v2=True) @property def get_place_name(self): tr = get_cached_translation(self.place) if tr is None: tr = get_translation(self.place) set_cached_translation(self.place, tr) return self.place.name def get_event_place_name(self): if self.place: return self.get_place_name return getattr(self, 'place_alt', None) def get_permanent_url(self): url = '%s%s/'%(self.get_catalog_url(), self.url) return url def get_main_link(self): if self.main: return self.main.link.get_click_link() else: return self.get_permanent_url() def get_paid_catalog_url(self): return self.paid_new.catalog.get_click_link() def org_split(self): if self.org: return self.org.split(';') else: return [] def get_logo(self): return self.logo def get_preview(self): preview = self.files.filter(purpose='preview') if preview: return preview[0] return preview def get_photos(self): if self.photogallery: return self.photogallery.photos.language().all() else: return None """ photos = self.files.filter(purpose='photo') return photos """ def on(self): self.is_published = True self.canceled_by_administrator = False self.save() def off(self): self.is_published = False self.canceled_by_administrator = True self.save() def cancel(self): self.canceled_by_administrator = True def duration_days(self, month=None): if not month: d = self.data_end - self.data_begin return d.days+1 else: if self.data_begin.month == month and self.data_end.month ==month: d = self.data_end - self.data_begin return d.days + 1 if self.data_begin.month == month: last_day = python_calendar.monthrange(self.data_begin.year, month)[1] return last_day - self.data_begin.day + 1 if self.data_end.month == month: return self.data_end.day return 0 def upload_photo(self, photo, gallery=None): """ uploading photo to gallery """ if gallery is None: gallery = self.get_gallery() gallery.photos.add(photo) def get_gallery(self): if self.photogallery: return self.photogallery data = {} model = type(self) for code, name in settings.LANGUAGES: # access to translated fields obj = model._meta.translations_model.objects.get(language_code=code, master__id=self.id) #access to translated fields data['title_%s' % code] = obj.name data['description_%s ' % code] = obj.description gallery = Gallery() fill_with_signal(Gallery, gallery, data) self.photogallery = gallery self.save() return gallery def tags(self): return self.tag.language().all() def copy(self, url): """ Copy event with new url :param url: new url for event :return: event object """ # check url Model = type(self) try: Model.objects.get(url=url) return _(u'Событие с таким урлом уже существует') except Model.DoesNotExist: pass duplicate = copy.copy(self) duplicate.url = url # Setting pk to None. for Django its a new object. duplicate.pk = None # copy translations ignore_fields = ['id', 'master', 'language_code'] duplicate.translate('ru') tr = self._meta.translations_model.objects.get(language_code='ru', master__id=self.pk) for field in duplicate._translated_field_names: if field in ignore_fields: continue setattr(duplicate, field, getattr(tr, field)) duplicate.is_published = False duplicate.save() # save but lost all ManyToMany relations # copy relations for field in self._meta.many_to_many: source = getattr(self, field.attname) destination = getattr(duplicate, field.attname) for item in source.all(): destination.add(item) return duplicate class GetURLorPK(object): @property def url_or_pk(self): return self.url or self.pk