# -*- coding: utf-8 -*- import dateutil.relativedelta as rdelta import json import datetime import calendar as python_calendar from sorl.thumbnail import get_thumbnail from django.core.urlresolvers import reverse, reverse_lazy from django.shortcuts import get_object_or_404 from django.http import HttpResponseRedirect, HttpResponse, Http404, HttpResponseBadRequest, HttpResponseForbidden from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _, get_language from django_messages.forms import SendForm from django.views.generic import TemplateView, FormView, RedirectView # from django.views.generic.detail import SingleObjectMixin from django.conf import settings from meta.views import MetadataMixin from functions.custom_views import ListView, CreateUpdateView, AjaxableResponseMixin, ContextMixin from functions.views_help import dates_range, get_user from exposition.models import Exposition from city.models import City from theme.models import Theme, Tag from company.forms import CreateCompanyForm from company.edit_forms import NameForm as CompNameForm, HomeForm as CompHomeForm, PhoneForm as CompPhoneForm,\ EmailForm as CompEmailForm, WebPageForm as CompWebPageForm, SocialForm as CompSocialForm,\ TagForm as CompTagForm, DescriptionForm as CompDescr, StaffForm as CompStaff, \ FoundationForm as CompFound, SpecializationForm as CompSpec, AddressForm as CompAddress from emencia.django.newsletter.forms import SubscribeSettingsForm from emencia.django.newsletter.models import Contact, ContactSettings from .forms import ChangePasswordForm, FeedFilterForm from .models import User from .edit_forms import AvatarForm, NameForm, HomeForm, WorkForm, AboutCompanyForm, PhoneForm, EmailForm,\ WebPageForm, SocialForm, AboutForm # FIXME: сделать рефакторинг + если не подтверждена подписка, # при заходе на стр настройки рассылки - 500 class SettingsView(CreateUpdateView): """ display template with user settings like: password, email notifications, social settings, subscription """ form_class = SubscribeSettingsForm template_name = 'client/accounts/settings.html' success_url = reverse_lazy('accounts_settings') def get_object(self): user = self.request.user try: self.contact = Contact.objects.get(user=user) except Contact.DoesNotExist: try: self.contact = Contact.objects.get(email=user.username, user__isnull=True) self.contact.user = user self.contact.save() except Contact.DoesNotExist: self.contact = None return None try: obj = ContactSettings.objects.get(contact_id=self.contact.pk) except ContactSettings.DoesNotExist: obj = ContactSettings.objects.create( contact=self.contact, exponent_practicum=False, organiser_practicum=False ) return obj def form_valid(self, form): if not self.contact: email = form.cleaned_data['email'] self.contact = Contact.objects.create_contact(email, self.request.user) form.activation_send = True self.object = form.save(commit=False) self.object.contact = self.contact self.object.save() form.save_m2m() form.save_additional_fields(self.object) form.make_pretty_city_val() return self.render_to_response(self.get_context_data(form=form)) def get_form_kwargs(self): kwargs = super(SettingsView, self).get_form_kwargs() kwargs.update({ 'initial': {'email': getattr(self.contact, 'email', self.request.user.email)}, 'contact': self.contact, }) return kwargs def get_context_data(self, **kwargs): context = super(SettingsView, self).get_context_data(**kwargs) context['change_password_form'] = ChangePasswordForm() return context class GetUserMixin(object): def get_user(self): instance = None if self.request.user.is_authenticated(): try: instance = Contact.objects.filter(user=self.request.user).prefetch_related('themes', 'tags')[0] except IndexError: try: instance = Contact.objects.filter(email=self.request.user.email).prefetch_related('themes', 'tags')[0] except IndexError: pass elif 'ml_contact_pk' in self.request.session: try: instance = Contact.objects.filter(pk=self.request.session['ml_contact_pk']).prefetch_related('themes', 'tags')[0] except IndexError: pass return instance class CalendarView(TemplateView): """ display template with user calendar(one month) """ template_name = 'client/accounts/calendar.html' def get_context_data(self, **kwargs): """ get events by 1 month and return to template return additional variables: - events - events in current months - days - days in current month - current_day """ context = super(CalendarView, self).get_context_data(**kwargs) now = datetime.datetime.now().replace(microsecond=0, second=0, minute=0, hour=0) context['current_day'] = now year = self.request.GET.get('year') month = self.request.GET.get('month') if year: year = int(year) if month: month = int(month) if not year or not month: # events in current months number_of_days = python_calendar.monthrange(now.year, now.month)[1] # number of days in current month days = [datetime.datetime(now.year, now.month, i+1) for i in range(number_of_days)] calendar = self.request.user.calendar # events in current month context['events'] = calendar.events_by_month(now) else: number_of_days = python_calendar.monthrange(year, month)[1] # days in current month days = [datetime.datetime(year, month, i+1) for i in range(number_of_days)] calendar = self.request.user.calendar now = now.replace(year=year, month=month, day=1) # events in current month context['events'] = calendar.events_by_month(now) # add days from previous monday to next sunday first_day = days[0] if first_day.weekday() != 0: past_monday = first_day + rdelta.relativedelta(days=-1, weekday=rdelta.MO(-1)) a = [past_monday + datetime.timedelta(days=x) for x in range((first_day - past_monday).days)] days = a + days last_day = days[-1] if last_day != 6: next_sunday = last_day + rdelta.relativedelta(days=1, weekday=rdelta.SU(+1)) b = [last_day + datetime.timedelta(days=x+1) for x in range((next_sunday - last_day).days)] days += b events = context['events'] context['days'] = days dates_with_events = [] for event in events: dates_with_events += dates_range(event.data_begin, event.data_end) dates_with_events = list(set(dates_with_events)) day_colspan = {} for day in days: if day.date() in dates_with_events: day_colspan[day] = {'event': True} else: day_colspan[day] = {'event': False} previous_day = day - datetime.timedelta(days=1) if previous_day not in days: day_colspan[day]['start'] = day else: if day_colspan[previous_day]['event']: day_colspan[day]['start'] = day else: day_colspan[day]['start'] = day_colspan[previous_day]['start'] if day_colspan[day_colspan[day]['start']].get('counter'): day_colspan[day_colspan[day]['start']]['counter'] += 1 else: day_colspan[day_colspan[day]['start']]['counter'] = 1 context['day_colspan'] = day_colspan return context class ProfileCompanyView(TemplateView): """ display template with user company information forms in template forms handles dynamically by ajax """ template_name = 'accounts/fill_company.html' def get_context_data(self, **kwargs): context = super(ProfileCompanyView, self).get_context_data(**kwargs) user = self.request.user if not user.company: raise Http404 company = user.company forms = { 'home_form': CompHomeForm(instance=company), 'phone_form': CompPhoneForm(instance=company), 'email_form': CompEmailForm(instance=company), 'web_page_form': CompWebPageForm(instance=company), 'social_form': CompSocialForm(instance=company), 'tag_form': CompTagForm(instance=company), 'staff_form': CompStaff(instance=company), 'found_form': CompFound(instance=company) } lang = get_language() comp_transl = company.translations.get(language_code=lang) transl_forms = { 'name_form': CompNameForm(instance=comp_transl), 'spec_form': CompSpec(instance=comp_transl), 'description_form': CompDescr(instance=comp_transl), 'address_form': CompAddress(instance=comp_transl) } context.update(forms) context.update(transl_forms) return context class UserMixin(object): def get_user(self): url = self.kwargs.get('url') try: user = User.objects.get(id=int(url)) except (ValueError, User.DoesNotExist, ): user = get_object_or_404(User, url=url) self.kwargs['user_full_name'] = user.get_full_name() return user class UserView(UserMixin, MetadataMixin, TemplateView): """ display user information for another users """ template_name = 'client/accounts/user.html' def get_context_data(self, **kwargs): user = self.get_user() context = super(UserView, self).get_context_data(**kwargs) if user == self.request.user: profile = user.profile profile_forms = { 'avatar_form': AvatarForm(instance=profile), 'name_form': NameForm(instance=user), 'home_form': HomeForm(instance=profile), 'work_form': WorkForm(instance=user), 'about_company_form': AboutCompanyForm(instance=profile), 'phone_form': PhoneForm(instance=profile), 'email_form': EmailForm(instance=user), 'web_page_form': WebPageForm(instance=profile), 'social_form': SocialForm(instance=profile), 'about_form': AboutForm(instance=profile), 'company_form': CreateCompanyForm() } context.update(profile_forms) context['message_form'] = SendForm() context['member'] = user return context class ProfileInvalidView(FormView): """ abstract view. handles form errors. return errors in json """ def form_invalid(self, form): response = {'success': False} response.update({'errors': form.errors}) return HttpResponse(json.dumps(response), content_type='application/json') class BaseProfileView(ProfileInvalidView): """ abstract view for ajax calls. handles form with instance profile return json """ def form_valid(self, form): profile = self.request.user.profile form = self.form_class(self.request.POST, instance=profile) profile = form.save() response = {'success': True, 'rating': profile.user.rating} return HttpResponse(json.dumps(response), content_type='application/json') class WorkView(ProfileInvalidView): """ instance user """ form_class = WorkForm def form_valid(self, form): user = self.request.user form = self.form_class(self.request.POST, instance=user) user = form.save() response = {'success': True, 'rating': user.rating} return HttpResponse(json.dumps(response), content_type='application/json') class AvatarView(BaseProfileView): """ instance profile. save user avatar. if call is ajax- return json data, else redirect to profile page """ form_class = AvatarForm def form_valid(self, form): profile = self.request.user.profile form = self.form_class(self.request.POST, self.request.FILES, instance=profile) profile = form.save() if self.request.is_ajax(): im = get_thumbnail(profile.avatar, '100x100', format="PNG") response = {'success': True, 'url': im.url, 'rating': profile.user.rating} return HttpResponse(json.dumps(response), content_type='application/json') else: return HttpResponseRedirect('/profile/') class HomeView(BaseProfileView): """ instance profile """ form_class = HomeForm class AboutCompanyView(BaseProfileView): """ instance profile """ form_class = AboutCompanyForm class PhoneView(BaseProfileView): """ instance profile """ form_class = PhoneForm class WebPageView(BaseProfileView): """ instance profile """ form_class = WebPageForm class SocialView(BaseProfileView): """ instance profile """ form_class = SocialForm class AboutView(BaseProfileView): """ instance profile """ form_class = AboutForm class NameView(ProfileInvalidView): """ instance user """ form_class = NameForm def form_valid(self, form): user = self.request.user form = self.form_class(self.request.POST, instance=user) user = form.save() response = {'success': True, 'rating': user.rating} return HttpResponse(json.dumps(response), content_type='application/json') class UserEventView(ListView): model = Exposition template_name = 'client/accounts/user_events.html' paginate_by = 10 obj = None event_type = None # def get_queryset(self): # url = self.kwargs.get('url') # user = get_user(url) # self.obj = user # return user.exposition_users.language().select_related('country').all() def get_context_data(self, **kwargs): context = super(UserEventView, self).get_context_data(**kwargs) context['u'] = self.obj context['event_type'] = self.event_type return context class UserExpositionsView(UserMixin, MetadataMixin, UserEventView): """ return template with list of expos that user joined """ event_type = _(u'Выставки') def get_queryset(self): user = self.get_user() self.obj = user self.kwargs['user_full_name'] = user.get_full_name() return user.get_expos() class UserConferenceView(UserMixin, MetadataMixin, UserEventView): """ return template with list of confs that user joined """ event_type = _(u'Конференции') def get_queryset(self): user = self.get_user() self.obj = user self.kwargs['user_full_name'] = user.get_full_name() return user.get_confs() @login_required def change_password(request): """ Change current user password if new password is valid """ success = {'success': False} if request.POST: form = ChangePasswordForm(request.POST) if form.is_valid(): user = request.user if(user.check_password(form.cleaned_data.get('old_password'))): user.set_password(form.cleaned_data.get('new_password')) user.save() success['success'] = True success['message'] = _(u'Пароль изменен') return HttpResponse(json.dumps(success), content_type='application/json') else: errors = {'errors': [_(u'Не правильный пароль')]} success.update(errors) return HttpResponse(json.dumps(success), content_type='application/json') else: errors = [err[0] for err in form.errors.values()] errors = {'errors': errors} success.update(errors) return HttpResponse(json.dumps(success), content_type='application/json') else: return HttpResponse(json.dumps(success), content_type='application/json') class Feed(ListView): template_name = 'client/accounts/feed.html' paginate_by = settings.CLIENT_PAGINATION model = Exposition filter_form = FeedFilterForm success_url = '/profile/feed/' def post(self, request): user = self.request.user form = self.filter_form(request.POST, user=user) if form.is_valid(): form.filter_save() return HttpResponseRedirect(self.success_url) def get_queryset(self): filter_obj = self.request.user.eventfilter qs = filter_obj.get_queryset() return qs def get_context_data(self, **kwargs): context = super(Feed, self).get_context_data(**kwargs) user = self.request.user filter_form = self.filter_form(user=user) context['filter_form'] = filter_form return context @login_required def remove_from_calendar(request): if request.GET: expo = request.GET.get('expo') conf = request.GET.get('conf') seminar = request.GET.get('seminar') webinar = request.GET.get('webinar') data = {'expo': expo if expo is None else json.loads(expo), 'conf': conf if conf is None else json.loads(conf), 'seminar': seminar if seminar is None else json.loads(seminar), 'webinar': webinar if webinar is None else json.loads(webinar)} user = request.user user.remove_from_calendar(data) return HttpResponse(json.dumps({'success': True}), content_type='application/json') else: return Http404 # @login_required # def get_user_subscribe_themes_tags(request): # """ # Ajax представление получения списка тем и тегов рассылки, # на которые подписан пользователь # """ # data = {'success': False} # if request.is_ajax(): # data['success'] = True # # user_themes = request.user # return HttpResponse(json.dumps(data), content_type='application/json') class UserSubscribeThemesTagsView(GetUserMixin, TemplateView): """ Ajax представление получения списка тем и тегов рассылки, на которые подписан пользователь """ content_type = 'application/json' def get_context_data(self, **kwargs): ctx = super(UserSubscribeThemesTagsView, self).get_context_data(**kwargs) data = [] instance = self.get_user() user_themes = [] user_tags = [] themes = Theme.objects.language().values('pk', 'name') if instance is not None: user_themes = instance.themes.values_list('pk', flat=True) user_tags = instance.tags.values_list('pk', flat=True) for theme in themes: tags = [] for tag in Tag.objects.language().filter(theme_id=theme['pk']).values('pk', 'name').order_by('name'): tags.append({ 'id': tag['pk'], 'checked': True if tag['pk'] in user_tags else False, 'text': tag['name'] }) data.append({ 'id': theme['pk'], 'text': theme['name'], 'checked': True if theme['pk'] in user_themes else False, 'tags': tags }) ctx['success'] = True ctx['data'] = data return ctx def render_to_response(self, context, **response_kwargs): context.pop('view') return HttpResponse( json.dumps(context), content_type=self.content_type )