# -*- coding: utf-8 -*- from django.contrib.auth.models import ( AbstractBaseUser, BaseUserManager, PermissionsMixin ) from django.core.mail import send_mail from django.db import models from django.db.models import Q from django.db.models.loading import get_model from django.db.models.signals import post_save from django.utils import timezone from django.utils.translation import ugettext as _ from functions.form_check import translit_with_separator from functions.model_mixin import GetURLorPK class UserLog(models.Model): # class Meta: # pass user = models.ForeignKey('accounts.User', verbose_name=_(u'Пользователь')) referer1 = models.TextField( verbose_name=_(u'Первый переход'), null=True, blank=True) referer2 = models.TextField( verbose_name=_(u'Второй переход'), null=True, blank=True) utm_source1 = models.TextField(null=True, blank=True) utm_medium1 = models.TextField(null=True, blank=True) utm_campaign1 = models.TextField(null=True, blank=True) utm_source2 = models.TextField(null=True, blank=True) utm_medium2 = models.TextField(null=True, blank=True) utm_campaign2 = models.TextField(null=True, blank=True) search1 = models.TextField(null=True, blank=True) search2 = models.TextField(null=True, blank=True) search3 = models.TextField(null=True, blank=True) class UserManager(BaseUserManager): """ Creates and saves a User with the given email, first_name, last_name and password. """ def create_user(self, email, first_name, last_name, password=None, **extra_fields): now = timezone.now() if not email: raise ValueError(_(u'Вы должни ввести электронную почту')) user = self.model( email=UserManager.normalize_email(email), first_name=first_name,last_name = last_name, username=UserManager.normalize_email(email), is_staff=False, is_active=False, is_superuser=False, last_login=now, date_joined=now, **extra_fields ) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, username, first_name, last_name, password, **extra_fields): if not username: raise ValueError(_(u'Вы должни ввести электронную почту')) username = UserManager.normalize_email(username) user = self.create_user( email=username, first_name=first_name, last_name=last_name, password=password, **extra_fields ) user.is_staff = True user.is_active = True user.is_superuser = True user.is_admin = True user.save(using=self._db) return user def safe_get(self, **kwargs): model = self.model try: return model.objects.get(**kwargs) except: return None class User(AbstractBaseUser, PermissionsMixin, GetURLorPK): """ Implementing a fully featured User model with admin-compliant permissions. stored main data about users Email, first name, last name and password are required. Other fields are optional. """ catalog = '/user/' email = models.EmailField( verbose_name=u'Email', max_length=255, #unique = True, db_index=True, ) username = models.CharField(verbose_name=_(u'Email'), max_length=255, unique=True, db_index=True) first_name = models.CharField(verbose_name=_(u'First name'), max_length=255) last_name = models.CharField(verbose_name=_(u'Last name'), max_length=255) rating = models.IntegerField(verbose_name=_(u'Рейтинг'), default=100)# добавить индекс в базе url = models.SlugField(verbose_name=_(u'Url'), blank=True) is_active = models.BooleanField(verbose_name=_(u'Активный'), default=0) is_staff = models.BooleanField(verbose_name=_(u'Сотрудник?'), default=0) is_admin = models.BooleanField(verbose_name=_(u'Админ?'), default=0) date_joined = models.DateTimeField(verbose_name=_(u'Дата создания'), auto_now_add=True) date_registered = models.DateTimeField(verbose_name=_(u'Дата регистрации'), blank=True, null=True) date_modified = models.DateTimeField(verbose_name=_(u'Изменен'), auto_now=True) #relations organiser = models.ForeignKey('organiser.Organiser', verbose_name=_(u'Организатор'), blank=True, null=True, unique=True, on_delete=models.PROTECT) translator = models.ForeignKey('translator.Translator', verbose_name=_(u'Переводчик'), blank=True, null=True, unique=True, on_delete=models.PROTECT, related_name='user') company = models.ForeignKey('company.Company', verbose_name=_(u'Компания'), blank=True, null=True, related_name='users') position = models.CharField(verbose_name=_(u'Должность'), max_length=255, blank=True) blocked = models.BooleanField(verbose_name=_(u'Заблокирован?'), default=False) readonly = models.BooleanField(_(u'Read Only'), default=False) objects = UserManager() USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['first_name', 'last_name'] class Meta: ordering = ['-rating'] def get_user_log(self): try: log, created = UserLog.objects.get_or_create(user_id=self.pk) except (UserLog.MultipleObjectsReturned, ): log = UserLog.objects.filter(user_id=self.pk)[0] return log def get_full_name(self): """ Returns the first_name plus the last_name, with a space in between. """ return u'%s %s'%(self.first_name, self.last_name) def set_url(self, st): self.url = translit_with_separator(u'%s'%st) def __unicode__(self): return self.email def get_short_name(self): """Returns the short name for the user.""" return self.first_name def email_user(self, subject, message, from_email=None): """ Sends an email to this User. """ send_mail(subject, message, from_email, [self.email]) def has_perm(self, perm, obj=None): return True def has_module_perms(self, app_label): return True def get_expositions_number(self): # 1 query return self.exposition_users.all().count() def get_conferences_number(self): # 1 query return self.conference_users.all().count() def get_seminars_number(self): # 1 query return self.seminar_users.all().count() def get_webinars_number(self): # 1 query return self.webinar_users.all().count() def get_events_number(self): # 4 query n = self.get_expositions_number() + self.get_conferences_number() + self.get_seminars_number() + self.get_webinars_number() return n def get_permanent_url(self): if self.url: return '/%s/' % self.url return '/%d/' % self.id def get_expos(self): """ return information about expos and them related data by 1 query(reverse connection) """ return self.exposition_users.language().select_related('country', 'city', 'place').all() def get_confs(self): """ return information about confs and them related data by 1 query(reverse connection) """ return self.conference_users.language().select_related('country', 'city', 'place').all() def remove_from_calendar(self, data): expo = data['expo'] conf = data['conf'] calendar = self.calendar if expo: calendar.expositions.remove(*expo) if conf: calendar.conferences.remove(*conf) class Profile(models.Model): """ stores additional information about users """ user = models.OneToOneField(User) country = models.ForeignKey('country.Country', verbose_name=_(u'Страна'), blank=True, null=True, on_delete=models.PROTECT, related_name='users') city = models.ForeignKey('city.City', verbose_name=_(u'Город'), blank=True, null=True, on_delete=models.PROTECT) about_company = models.TextField(verbose_name=_(u'Описание компании'), blank=True) phone = models.BigIntegerField(verbose_name=_(u'Телефон'), blank=True, null=True) show_phone = models.NullBooleanField(verbose_name=_(u'Показывать телефон'), blank=True, null=True, default=1) web_page = models.URLField(verbose_name=_(u'Вебсайт'),blank=True) about = models.TextField(verbose_name=_(u'О себе'), blank=True) avatar = models.ImageField(verbose_name=_(u'Фото'), upload_to='accounts/avatar/', blank=True) skype = models.CharField(verbose_name=_(u'Skype'), blank=True, max_length=255) facebook = models.URLField(verbose_name=_(u'Facebook'), blank=True, max_length=255) twitter = models.URLField(verbose_name=_(u'Twitter'), blank=True,max_length=255) linkedin = models.URLField(verbose_name=_(u'LinkedIn'), blank=True, max_length=255) vk = models.URLField(verbose_name=_(u'В контакте'), blank=True, max_length=255) # meta title = models.CharField(max_length=255, blank=True) descriptions = models.CharField(max_length=255, blank=True) keywords = models.CharField(max_length=255, blank=True) class Calendar(models.Model): """ Store information about events, which user can add to own calendar every user has one calendar """ user = models.OneToOneField(User) expositions = models.ManyToManyField('exposition.Exposition', verbose_name=_(u'Выставки'), null=True) conferences = models.ManyToManyField('conference.Conference', verbose_name=_(u'Конфеернции'), null=True) seminars = models.ManyToManyField('seminar.Seminar', verbose_name=_(u'Семинары'), null=True) webinars = models.ManyToManyField('webinar.Webinar', verbose_name=_(u'Вебинары'), null=True) def get_expos(self): # 1 query _get_expos = getattr(self, '_get_expos', None) if _get_expos is None: self._get_expos = list(self.expositions.language().all()) return self._get_expos def get_expos_ids(self): # 1 query _get_expos_ids = getattr(self, '_get_expos_ids', None) if _get_expos_ids is None: self._get_expos_ids = list(self.expositions.all().values_list('pk', flat=True)) return self._get_expos_ids def get_confs(self): # 1 query _get_confs = getattr(self, '_get_confs', None) if _get_confs is None: self._get_confs = list(self.conferences.language().all()) return self._get_confs def get_confs_ids(self): # 1 query _get_confs_ids = getattr(self, '_get_confs_ids', None) if _get_confs_ids is None: self._get_confs_ids = list(self.conferences.all().values_list('pk', flat=True)) return self._get_confs_ids def get_seminars(self): # 1 query _get_seminars = getattr(self, '_get_seminars', None) if _get_seminars is None: self._get_seminars = list(self.seminars.language().all()) return self._get_seminars def get_seminars_ids(self): # 1 query _get_seminars_ids = getattr(self, '_get_seminars_ids', None) if _get_seminars_ids is None: self._get_seminars_ids = list(self.seminars.all().values_list('pk', flat=True)) return self._get_seminars_ids def get_webinars(self): # 1 query _get_webinars = getattr(self, '_get_webinars', None) if _get_webinars is None: self._get_webinars = list(self.webinars.language().all()) return self._get_webinars def get_webinars_ids(self): # 1 query _get_webinars_ids = getattr(self, '_get_webinars_ids', None) if _get_webinars_ids is None: self._get_webinars_ids = list(self.webinars.all().values_list('pk', flat=True)) return self._get_webinars_ids def get_events(self): # 4 query events = self.get_expos() + self.get_confs() + self.get_seminars() + self.get_webinars() return events def check_in_calendar(self, event): """ check if event in calendar 1 query """ event_type = event.event_type if event_type == 'expo': return event in self.get_expos_ids() elif event_type == 'conf': return event in self.get_confs_ids() elif event_type == 'seminar': return event in self.get_seminars_ids() elif event_type == 'webinar': return event in self.get_webinars_ids() def events_by_month(self, day): exp = list(self.expositions.filter((Q(data_begin__month=day.month) & Q(data_begin__year=day.year))\ | (Q(data_end__month=day.month) & Q(data_end__year=day.year)))) con = list(self.conferences.filter((Q(data_begin__month=day.month) & Q(data_begin__year=day.year))\ | (Q(data_end__month=day.month) & Q(data_end__year=day.year)))) sem = list(self.seminars.filter((Q(data_begin__month=day.month) & Q(data_begin__year=day.year))\ | (Q(data_end__month=day.month) & Q(data_end__year=day.year)))) web = list(self.webinars.filter(Q(data_begin__month=day.month)&Q(data_begin__year=day.year))) return exp+con+sem+web class EventFilter(models.Model): user = models.OneToOneField(User) theme = models.ManyToManyField('theme.Theme', verbose_name=_(u'Тематики'), null=True) tag = models.ManyToManyField('theme.Tag', verbose_name=_(u'Теги'), null=True) area = models.ManyToManyField('country.Area', verbose_name=_(u'Геограифческие зоны'), null=True) country = models.ManyToManyField('country.Country', verbose_name=_(u'Страны'), null=True) city = models.ManyToManyField('city.City', verbose_name=_(u'Города'), null=True) fr = models.DateField(blank=True, verbose_name=_(u'с'), null=True) to = models.DateField(blank=True, verbose_name=_(u'до'), null=True) def get_queryset(self): """ get filtered queryset """ Exposition = get_model('exposition', 'Exposition') qs = Exposition.enable.upcoming() themes = self.theme.all() tags = self.tag.all() countries = self.country.all() areas = self.area.all() cities = self.city.all() if themes.exists(): qs = qs.filter(theme__in=set(themes)) if tags.exists(): qs = qs.filter(tag__in=set(tags)) if cities.exists(): qs = qs.filter(city__in=set(cities)) if areas.exists(): qs = qs.filter(country__area__in=set(areas)) if countries.exists(): qs = qs.filter(country__in=set(countries)) return qs.order_by('data_begin').distinct() def calculate_rating(user): """ calculates user rating depending og user filled information calls in post save signal of profile model """ user_rating_fields = {'position': 5, 'company': 5, 'url': 10} profile_rating_fields = {'country': 5, 'city': 5, 'phone': 10, 'facebook': 5, 'twitter': 5, 'linkedin': 5, 'vk': 5, 'web_page': 10, 'avatar': 20, 'about': 15} ''' TODO: доделать "Отметки на выставках, за каждую", "Подписка на рассылку", "Добавление фото, за каждую", "Добавление компании, за каждую опубликованную" ''' # base rating rating = 100 for key, value in user_rating_fields.iteritems(): if getattr(user, key): rating += value for key, value in profile_rating_fields.iteritems(): if getattr(user.profile, key): rating += value user.rating = rating # call to prevent recursion post_save.disconnect(create_user_inf, sender=User) user.save() post_save.connect(create_user_inf, sender=User) def create_user_inf(sender, instance, created, **kwargs): """ create default models that is required for users """ if created: Calendar.objects.create(user=instance) Profile.objects.create(user=instance) EventFilter.objects.create(user=instance) calculate_rating(instance) def post_profile(sender, instance, created, **kwargs): user = instance.user calculate_rating(user) post_save.connect(create_user_inf, sender=User) post_save.connect(post_profile, sender=Profile)