You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
376 lines
13 KiB
376 lines
13 KiB
# -*- coding: utf-8 -*-
|
|
import copy
|
|
import calendar as python_calendar
|
|
from itertools import chain
|
|
|
|
from pytils.dt import ru_strftime
|
|
import datetime
|
|
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:
|
|
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, '_nearest_events', None) is None:
|
|
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) > 5:
|
|
qs = model.objects.language()
|
|
r, e = self.get_nearest_events_incl(qs, tags, themes, exclude)
|
|
result += r
|
|
self._nearest_events = result[3:5]
|
|
return self._nearest_events
|
|
|
|
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
|
|
|