# -*- coding: utf-8 -*- from django.db import models from django.db.models.signals import post_save, pre_save from django.utils.translation import ugettext as _ from hvad.models import TranslatableModel, TranslatedFields, TranslationManager import copy, datetime from django.contrib.contenttypes import generic from bitfield import BitField from service.models import Service from functions.db import db_table_exists from organiser.models import Organiser # from functions.custom_fields import EnumField from functions.signal_handlers import post_save_handler, pre_save_handler from functions.models_methods import ExpoManager from functions.model_mixin import EventMixin AUDIENCE1 = ((None,_(u'Не выбрано')), ('experts', _(u'Специалисты')), ('experts and consumers', _(u'Специалисты и потребители')), ('general public', _(u'Широкая публика')) ) AUDIENCE = (None,'experts', 'experts and consumers', 'general public') BIT_AUDIENCE = (('experts', _(u'Специалисты')), ('experts and consumers', _(u'Специалисты и потребители')), ('general public', _(u'Широкая публика'))) CURRENCY = ('RUB', 'USD', 'EUR') # check if table exist and create flags if true flags = [str(item.id) for item in Service.objects.all()] if db_table_exists('service_service') else [] class Exposition(TranslatableModel, EventMixin): """ Create Exposition model Uses hvad.TranslatableModel which is child of django.db.models class """ #set manager of this model objects = ExpoManager() url = models.SlugField(unique=True) data_begin = models.DateField(verbose_name='Дата начала') data_end = models.DateField(verbose_name='Дата окончания') services = BitField(flags=flags) quality_label = BitField(flags=['ufi', 'rsva', 'exporating']) audience = BitField(flags=[k for k, v in BIT_AUDIENCE]) # relations country = models.ForeignKey('country.Country', verbose_name='Страна', on_delete=models.PROTECT) city = models.ForeignKey('city.City', verbose_name='Город', on_delete=models.PROTECT) place = models.ForeignKey('place_exposition.PlaceExposition', verbose_name='Место проведения', blank=True, null=True, on_delete=models.PROTECT, related_name='exposition_place') theme = models.ManyToManyField('theme.Theme', verbose_name='Тематики', related_name='exposition_themes') tag = models.ManyToManyField('theme.Tag', verbose_name='Теги', blank=True, null=True, related_name='exposition_tags') organiser = models.ManyToManyField('organiser.Organiser', verbose_name='Организатор', blank=True, null=True, related_name='exposition_organisers') company = models.ManyToManyField('company.Company', verbose_name='Компании', blank=True, null=True, related_name='exposition_companies') users = models.ManyToManyField('accounts.User', verbose_name='Посетители выставки', blank=True, null=True, related_name='exposition_users') periodic = models.FloatField(verbose_name='Переодичность', blank=True, null=True) #audience = EnumField(values=AUDIENCE, blank=True) web_page = models.CharField(verbose_name='Вебсайт', max_length=255, blank=True) min_area = models.PositiveIntegerField(verbose_name='Минимальная площадь', blank=True, null=True) # currency = EnumField(values=CURRENCY, default='RUB') application_deadline = models.DateField(verbose_name='Срок подачи заявки', null=True) min_stand_size = models.PositiveIntegerField(verbose_name='Минимальный размер стэнда', blank=True, null=True) price_day = models.PositiveIntegerField(verbose_name='Стоимость билета 1 день', blank=True, null=True) price_all = models.PositiveIntegerField(verbose_name='Стоимость билета все дни', blank=True, null=True) price_day_bar = models.PositiveIntegerField(verbose_name='Стоимость на стойке 1 день', blank=True, null=True) price_all_bar = models.PositiveIntegerField(verbose_name='Стоимость на стойке все дни', blank=True, null=True) price_catalog = models.PositiveIntegerField(verbose_name='Стоимость каталога', blank=True, null=True) tax = models.BooleanField(verbose_name='Налог', default=1) min_closed_area = models.PositiveIntegerField(verbose_name='Минимальная цена закрытой НЕ оборудованной площади', blank=True, null=True) max_closed_area = models.PositiveIntegerField(verbose_name='Максимальная цена закрытой НЕ оборудованной площади', blank=True, null=True) min_closed_equipped_area = models.PositiveIntegerField(verbose_name='Минимальная цена закрытой оборудованной площади', blank=True, null=True) max_closed_equipped_area = models.PositiveIntegerField(verbose_name='Максимальная цена закрытой оборудованной площади', blank=True, null=True) min_open_area = models.PositiveIntegerField(verbose_name='Минимальная цена открытой площади', blank=True, null=True) max_open_area = models.PositiveIntegerField(verbose_name='Максимальная цена открытой площади', blank=True, null=True) registration_payment = models.PositiveIntegerField(verbose_name='Регистрационный взнос', blank=True, null=True) discount = models.PositiveIntegerField(verbose_name='Скидка', blank=True, null=True) expohit = models.BooleanField(verbose_name='Expohit', default=0) # administrator can cancel exposition canceled_by_administrator = models.BooleanField(default=0) #can publish not immediately is_published = models.BooleanField(default=0) canceled = models.BooleanField(default=0) moved = models.BooleanField(default=0) files = generic.GenericRelation('file.FileModel', content_type_field='content_type', object_id_field='object_id') # statistic foundation_year = models.PositiveIntegerField(verbose_name='Год основания', blank=True, null=True) visitors = models.PositiveIntegerField(verbose_name='Посетители', blank=True, null=True) members = models.PositiveIntegerField(verbose_name='Участники', blank=True, null=True) translations = TranslatedFields( name = models.CharField(verbose_name='Название', max_length=255), main_title = models.TextField(verbose_name='Краткое описание', blank=True), description = models.TextField(verbose_name='Описание', blank=True), products = models.TextField(verbose_name='Экспонируемые продукты', blank=True), discount_description = models.TextField(verbose_name='Описание скидки', blank=True), time = models.TextField(verbose_name='Время работы', blank=True), #-----meta data title = models.CharField(max_length=250), descriptions = models.CharField(max_length=250), keywords = models.CharField(max_length=250), ) # field saves information about creating and changing model created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) main_page = models.PositiveIntegerField(default=0, db_index=True) views = models.PositiveIntegerField(default=0) def __unicode__(self): return self.lazy_translation_getter('name', unicode(self.pk)) def get_audience(self): checked = [item for item, bool in self.audience if bool==True] audience = [] for k, v in BIT_AUDIENCE: for item in checked: if item == k: audience.append(v) return ', '.join(audience) def get_periodic(self): periodic = {0: '', 1.0: _(u'Ежегодно'), 2.0: _(u'2 раза в год'), 3.0: _(u'3 раза в год'), 4.0: _(u'4 раза в год'), 5.0: _(u'5 раз в год'), 0.5: _(u'Раз в 2 года'), 0.33: _(u'Раз в 3 года'), 0.25: _(u'Раз в 4 года')} return periodic.get(self.periodic) def get_nearest_events(self): theme = self.theme.all()[0] now = datetime.datetime.now() now = now.replace(day=now.day-1) expositions = Exposition.objects.filter(theme__in=[theme], data_begin__gt=now).exclude(id=self.id) return expositions[3:] def get_catalog_url(self): return '/expositions/' def get_event_type(self): return _(u'Выставки') def get_calendar_url(self): return '/exposition-add-calendar/%s/'%self.id def get_visit_url(self): return '/exposition-visit/%s/'%self.id def clone(self): """ Return an identical copy of the instance with a new ID. """ if not self.pk: raise ValueError('Instance must be saved before it can be cloned.') duplicate = copy.copy(self) # Setting pk to None. Django thinking this is a new object. duplicate.pk = None # url must be unique duplicate.url += '_copy' if Exposition.objects.safe_get(url=duplicate.url): #already has copy this instance return # duplicate should not be published duplicate.is_published = False duplicate.cancel_by_administrator = False 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.save() # but lost all ManyToMany relations and Translations. # 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 Statistic(models.Model): exposition = models.ForeignKey(Exposition, related_name='statistic') year = models.PositiveIntegerField(verbose_name='Год') members = models.PositiveIntegerField(verbose_name='Посетители') visitors = models.PositiveIntegerField(verbose_name='Участники') from django.core import serializers from functions.models_methods import hvad_to_dict class TimeTable(TranslatableModel): """ TimeTable for business program """ exposition = models.ForeignKey(Exposition, related_name='business_program') begin = models.DateTimeField(verbose_name='Начало') end = models.DateTimeField(verbose_name='Конец') timetable_organiser = models.ForeignKey(Organiser, null=True, blank=True) # created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) #translated fields translations = TranslatedFields( programe = models.TextField(verbose_name='Программа'), speaker = models.CharField(verbose_name='Спикеры', max_length=255, blank=True) ) def to_dict(self): #obj = serializers.serialize('json', [self,]) return hvad_to_dict(self) class TmpTimeTable(TranslatableModel): exposition = models.ForeignKey(Exposition, null=True, blank=True) begin = models.DateTimeField(verbose_name='Начало') end = models.DateTimeField(verbose_name='Конец') timetable_organiser = models.ForeignKey(Organiser, null=True, blank=True) # key uses for checking keys from new objects. key = models.CharField(max_length=255, blank=True) # created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) #translated fields translations = TranslatedFields( programe = models.TextField(verbose_name='Программа'), speaker = models.CharField(verbose_name='Спикеры', max_length=255, blank=True) ) def clone(self, exposition=None): """ Return an identical copy of the instance with a new ID. """ if not self.pk: raise ValueError('Instance must be saved before it can be cloned.') duplicate = copy.copy(self) # Setting pk to None. Django thinking this is a new object. duplicate.pk = None duplicate.exposition = exposition 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.save() return duplicate pre_save.connect(pre_save_handler, sender=Exposition) post_save.connect(post_save_handler, sender=Exposition) post_save.connect(post_save_handler, sender=TimeTable) post_save.connect(post_save_handler, sender=TmpTimeTable)