# -*- 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 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, MailingSettingsForm from emencia.django.newsletter.models import Contact, ContactSettings from .forms import ChangePasswordForm, EmailAnnouncementForm, FeedFilterForm from .models import User from .edit_forms import AvatarForm, NameForm, HomeForm, WorkForm, AboutCompanyForm, PhoneForm, EmailForm,\ WebPageForm, SocialForm, AboutForm 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.get(user=self.request.user) except Contact.DoesNotExist: try: instance = Contact.objects.get(email=self.request.user.email) except Contact.DoesNotExist: pass elif 'ml_contact_pk' in self.request.session: try: instance = Contact.objects.get(pk=self.request.session['ml_contact_pk']) except Contact.DoesNotExist: pass return instance class MailingSettings(GetUserMixin, ContextMixin, AjaxableResponseMixin, CreateUpdateView): form_class = MailingSettingsForm template_name = 'client/accounts/mailing_settings.html' success_url = reverse_lazy('accounts-mailing_settings') def get_success_url(self): return self.success_url def get_object(self): self.extra_ctx.update({ 'r_cities': City.used.russia(), }) instance = self.get_user() if instance is not None: self.extra_ctx.update({ 'checked_f_countries': list(instance.f_countries.values_list('pk', flat=True)), 'checked_r_cities': list(instance.r_cities.values_list('pk', flat=True)), 'checked_tg': list(instance.tags.values_list('pk', flat=True)), 'checked_th': list(instance.themes.values_list('pk', flat=True)), }) elif not self.request.user.is_authenticated(): raise HttpResponseForbidden() return instance def form_valid(self, form): # print(form.cleaned_data) # print(form.errors) # print(self.request.POST) # import pdb; pdb.set_trace() return super(MailingSettings, self).form_valid(form) def form_invalid(self, form): # print(form.cleaned_data) # print(form.errors) # print(self.request.POST) return super(MailingSettings, self).form_invalid(form) class MailingSettingsUnsubscribe(GetUserMixin, RedirectView): url = reverse_lazy('accounts-mailing_settings') def get(self, request, *args, **kwargs): contact = self.get_user() if contact is None: return HttpResponseForbidden() if contact.subscriber: contact.unsubscribe() return super(MailingSettingsUnsubscribe, self).get(request, *args, **kwargs) 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