from django.conf import settings from django.contrib import messages from django.contrib.auth.mixins import PermissionRequiredMixin, LoginRequiredMixin from django.core.files.base import ContentFile from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.urlresolvers import reverse, reverse_lazy from django.db.models import Q from django.http import HttpResponseForbidden, HttpResponseRedirect, HttpResponse, Http404 from django.shortcuts import render, get_object_or_404, redirect from django.views.generic import ListView, DetailView, CreateView, DeleteView, View, UpdateView, TemplateView, FormView from django.views.generic.base import ContextMixin from pprint import pprint, pformat import json import pydash as _; _.map = _.map_; _.filter = _.filter_ import re from .mixins import LastAccessMixin from .models import Project, ProjectFile, Portfolio, PortfolioPhoto, Candidate, Answer, AnswerFile, AnswerMessage, Realty, Order from archilance.mixins import BaseMixin from users.models import User, Team from work_sell.models import Picture, WorkSell, WorkSellPhoto from .forms import ( ContractorPortfolioTrashForm, CustomerProjectDeleteForm, CustomerProjectEditForm, CustomerProjectRestoreForm, CustomerProjectTrashForm, PortfolioForm, ProjectAnswerForm, ProjectAnswerMessageForm, ProjectFilterForm, ProjectFilterRealtyForm, RealtyForm, ) class ProjectDetailWithAnswerView(BaseMixin, View): form_class = ProjectAnswerForm template_name = 'project_detail.html' def get(self, request, *args, **kwargs): context = self.get_context_data(**_.merge({}, request.GET, kwargs)) project = get_object_or_404(Project, pk=kwargs.get('pk')) context.update({'project': project}) if request.user.is_authenticated() and request.user.is_contractor(): project_answers = project.answers.all() contractor = request.user answer = _.first(_.filter(project_answers, lambda a: a.author == contractor)) if not answer: try: team = contractor.team except Team.DoesNotExist: team = None if team: answer = _.first(_.filter(project_answers, lambda a: a.author == team)) context.update({'answer': answer}) if not answer: try: contractor.team; context.update({'can_answer_as_team': True}) except Team.DoesNotExist: pass if request.GET.get('answer_as_team') == 'on': context.update({'answer_as_team': True}) form = self.form_class(request=request, answer_as_team=True, project=project) else: form = self.form_class(request=request, project=project) context.update({'form': form}) return render(request, self.template_name, context) def post(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_contractor(): context = self.get_context_data(**kwargs) answer_as_team = None project = get_object_or_404(Project, pk=kwargs.get('pk')) # TODO: Does this work? if request.POST.get('answer_as_team') == 'on': answer_as_team = True if answer_as_team: form = self.form_class(request.POST, request=request, answer_as_team=True, project=project) else: form = self.form_class(request.POST, request=request, project=project) project = get_object_or_404(Project, pk=kwargs.get('pk')) context.update({'project': project}) if form.is_valid(): answer = form.save(commit=False) answer.project = project answer.author = request.user.team if answer_as_team else request.user answer.save() form.save_m2m() for file in request.FILES.getlist('new_files'): if len(file.name) <= 255: AnswerFile.objects.create(file=file, name=file.name, answer=answer) message = AnswerMessage(text=form.cleaned_data.get('text'), is_sender_customer=False) message.answer = answer message.contractor_or_team = answer.author message.save() messages.info(request, 'Отклик успешно размещён') redirect_to = request.POST.get('next') return redirect(redirect_to) else: if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) context.update({'form': form}) return render(request, self.template_name, context) else: return HttpResponseForbidden('403 Forbidden') class ProjectAnswerCreateMessageView(BaseMixin, View): form_class = ProjectAnswerMessageForm def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated(): return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') def post(self, request, *args, **kwargs): form = self.form_class(request.POST, request=request) if form.is_valid(): message = form.save(commit=False) if request.user.is_contractor(): answer = get_object_or_404(Answer, pk=kwargs.get('pk')) message.answer = answer message.is_sender_customer = False if isinstance(answer.author, User) and answer.author == request.user: message.contractor_or_team = request.user elif isinstance(answer.author, Team): try: team = request.user.team except Team.DoesNotExist: team = None if team and answer.author == team: message.contractor_or_team = team elif request.user.is_customer(): answer = get_object_or_404(Answer, pk=kwargs.get('pk')) # TODO: Perform additional checks message.answer = answer message.is_sender_customer = True message.save() form.save_m2m() messages.info(request, 'Сообщение успешно размещено') else: if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) redirect_to = request.POST.get('next') return redirect(redirect_to) class ContractorRejectProjectAnswerView(BaseMixin, View): def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_contractor(): return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') def post(self, request, *args, **kwargs): answer = get_object_or_404(request.user.contractor_answers, pk=kwargs.get('pk')) answer.delete() messages.info(request, 'Вы успешно отказались от проекта') redirect_to = request.POST.get('next') return redirect(redirect_to) class CustomerRejectProjectAnswerView(BaseMixin, View): def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') def post(self, request, *args, **kwargs): answer_id = kwargs.get('pk') project = get_object_or_404(request.user.projects, answers__pk=answer_id) answer = get_object_or_404(project.answers, pk=answer_id) answer.delete() messages.info(request, 'Вы успешно отказали пользователю в проекте') redirect_to = request.POST.get('next') return redirect(redirect_to) class ProjectFilterView(BaseMixin, View): template_name = 'project_filter.html' form_class = ProjectFilterForm realty_form = ProjectFilterRealtyForm def get(self, request, *args, **kwargs): form = self.form_class(request.GET, request=request) realty_form = self.realty_form(request.GET, request=request, prefix='realty_form') context = self.get_context_data(**_.merge({}, request.GET, kwargs)) projects = Project.objects if form.is_valid() and realty_form.is_valid(): ord = None keywords = form.cleaned_data.get('keywords') cro = form.cleaned_data.get('cro') work_type = form.cleaned_data.get('work_type') specialization = form.cleaned_data.get('specialization') building_classification = realty_form.cleaned_data.get('building_classification') construction_type = realty_form.cleaned_data.get('construction_type') location = realty_form.cleaned_data.get('location') if keywords: keywords = tuple(filter(None, re.split(r'\s|,|;', keywords))) for k in keywords: projects = projects.filter(Q(name__icontains=k) | Q(text__icontains=k)) # projects = projects.filter(cro=cro) if work_type: projects = projects.filter(work_type=work_type) if specialization: projects = projects.filter( specialization__lft__gte=specialization.lft, specialization__rght__lte=specialization.rght, ) if building_classification: projects = projects.filter(realty__building_classification=building_classification) if construction_type: projects = projects.filter(realty__construction_type=construction_type) if location: projects = projects.filter( realty__location__lft__gte=location.lft, realty__location__rght__lte=location.rght, ) order_by = form.cleaned_data.get('order_by') last_order_by = form.cleaned_data.get('last_order_by') reverse_order = form.cleaned_data.get('reverse_order') if order_by: reverse_order = not reverse_order if order_by == last_order_by else False ord = order_by last_order_by = ord elif last_order_by: ord = last_order_by if ord: projects = projects.order_by('-%s' % ord if reverse_order else ord) context.update({ 'last_order_by': last_order_by, 'reverse_order': reverse_order, }) project_count = projects.count() display_msg = 'Найдено %s проектов' % project_count if project_count > 0 else 'Ничего не найдено' else: display_msg = 'Пожалуйста, введите корректные данные' if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) if realty_form and realty_form.errors: messages.info(request, ( '

Произошла ошибка (realty_form)

' '
{realty_form}
' ).format(realty_form=pformat(realty_form.errors))) paginator = Paginator(projects.all(), settings.PAGE_SIZE) page = request.GET.get('page') try: projects = paginator.page(page) except PageNotAnInteger: projects = paginator.page(1) except EmptyPage: projects = paginator.page(paginator.num_pages) context.update({ 'form': form, 'realty_form': realty_form, 'projects': projects, 'is_paginated': True, 'page_obj': projects, 'display_msg': display_msg, }) return render(request, self.template_name, context) class CustomerProjectCreateView(BaseMixin, View): form_class = CustomerProjectEditForm realty_form = RealtyForm template_name = 'customer_project_create.html' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') def get(self, request, *args, **kwargs): form = self.form_class(request=request) realty_form = self.realty_form(request=request, prefix='realty_form') context = self.get_context_data(**_.merge({}, request.GET, kwargs)) context.update({'form': form, 'realty_form': realty_form}) return render(request, self.template_name, context) def post(self, request, *args, **kwargs): form = self.form_class(request.POST, request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below form.is_valid() realty = form.cleaned_data.get('realty') if realty: realty_form = self.realty_form(request.POST, instance=realty, request=request, prefix='realty_form') else: realty_form = self.realty_form(request.POST, request=request, prefix='realty_form') if form.is_valid() and realty_form.is_valid(): project = form.save(commit=False) project.customer = request.user project.save() form.save_m2m() Order.objects.create(project=project) for file in request.FILES.getlist('new_files'): ProjectFile.objects.create(file=file, project=project) if realty: realty_form.save() else: realty = realty_form.save(commit=False) realty.user = request.user realty.save() realty_form.save_m2m() project.realty = realty # Connect a realty with a project project.save() messages.info(request, 'Проект успешно создан') redirect_to = reverse('projects:detail', kwargs={'pk': project.pk}) return redirect(redirect_to) else: if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) if realty_form and realty_form.errors: messages.info(request, ( '

Произошла ошибка (realty_form)

' '
{realty_form}
' ).format(realty_form=pformat(realty_form.errors))) context = self.get_context_data(**kwargs) context.update({'form': form, 'realty_form': realty_form}) return render(request, self.template_name, context) class CustomerProjectEditView(BaseMixin, View): form_class = CustomerProjectEditForm realty_form = RealtyForm template_name = 'customer_project_edit.html' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') def get(self, request, *args, **kwargs): project = get_object_or_404(request.user.projects, pk=kwargs.get('pk')) form = self.form_class(instance=project, request=request) realty = project.realty if realty: realty_form = self.realty_form(instance=project.realty, request=request, prefix='realty_form') else: realty_form = self.realty_form(request=request, prefix='realty_form') context = self.get_context_data(**_.merge({}, request.GET, kwargs)) context.update({'form': form, 'realty_form': realty_form}) return render(request, self.template_name, context) def post(self, request, *args, **kwargs): project = get_object_or_404(request.user.projects, pk=kwargs.get('pk')) form = self.form_class(request.POST, request.FILES, request=request, instance=project) form.is_valid() realty = form.cleaned_data.get('realty') if realty: realty_form = self.realty_form(request.POST, instance=realty, request=request, prefix='realty_form') else: realty_form = self.realty_form(request.POST, request=request, prefix='realty_form') if form.is_valid() and realty_form.is_valid(): project = form.save(commit=False) project.customer = request.user project.files = form.cleaned_data.get('files') # TODO: Should we somehow get rid of this explicit assignment? project.save() form.save_m2m() for file in request.FILES.getlist('new_files'): proj_file = ProjectFile.objects.create(file=file, project=project) proj_file.save() if realty: realty_form.save() else: realty = realty_form.save(commit=False) realty.user = request.user realty.save() realty_form.save_m2m() project.realty = realty # Connect a realty with a project project.save() messages.info(request, 'Проект успешно отредактирован') redirect_to = request.POST.get('next') return redirect(redirect_to) else: if form.errors: messages.info(request, ( '

Произошла ошибка (form)

' '
{form}
' ).format(form=pformat(form.errors))) if realty_form and realty_form.errors: messages.info(request, ( '

Произошла ошибка (realty_form)

' '
{realty_form}
' ).format(realty_form=pformat(realty_form.errors))) context = self.get_context_data(**kwargs) context.update({'form': form, 'realty_form': realty_form}) return render(request, self.template_name, context) class ContractorAnswerArchiveView(View): def post(self, request, *args, **kwargs): project_pk = request.POST.get('project_pk') user_pk = request.POST.get('user_pk') answer = Answer.objects.filter(project_id=project_pk,object_id=user_pk, content_type__model='user').first() answer.is_archive = True answer.save() redirect_to = request.POST.get('next') return redirect(redirect_to) class ContractorPortfolioTrashView(View): form_class = ContractorPortfolioTrashForm def post(self, request, *args, **kwargs): form = self.form_class(_.merge({}, request.POST, kwargs), request=request) if form.is_valid(): portfolio = form.cleaned_data.get('pk') portfolio.delete() messages.info(request, 'Портфолио удален') else: messages.info(request, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) redirect_to = request.POST.get('next') return redirect(redirect_to) class CustomerProjectTrashView(View): form_class = CustomerProjectTrashForm def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') def post(self, req, *args, **kwargs): form = self.form_class(_.merge({}, req.POST, kwargs), req=req) if form.is_valid(): project = form.cleaned_data.get('pk') project.state = 'trashed' project.save() messages.info(req, 'Проект перемещён в корзину') else: messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) redirect_to = req.POST.get('next') return redirect(redirect_to) class CustomerProjectRestoreView(View): form_class = CustomerProjectRestoreForm def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') def post(self, req, *args, **kwargs): form = self.form_class(_.merge({}, req.POST, kwargs), req=req) if form.is_valid(): project = form.cleaned_data.get('pk') project.state = 'active' project.save() messages.info(req, 'Проект восстановлен из корзины') else: messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) redirect_to = req.POST.get('next') return redirect(redirect_to) class CustomerProjectDeleteView(View): form_class = CustomerProjectDeleteForm def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: return HttpResponseForbidden('403 Forbidden') def post(self, req, *args, **kwargs): form = self.form_class(_.merge({}, req.POST, kwargs), req=req) if form.is_valid(): project = form.cleaned_data.get('pk') project.state = 'deleted' project.save() messages.info(req, 'Проект удалён навсегда') else: messages.info(req, 'Произошла ошибка:
{msg}
'.format(msg=pformat(form.errors))) redirect_to = req.POST.get('next') return redirect(redirect_to) class ProjectComparisonView(DetailView): model = Project template_name = 'comparison.html' def get_context_data(self, **kwargs): context = super().get_context_data() return context def add_candidate(request, answer_id, project_id): answer = Answer.objects.get(pk=answer_id) project = Project.objects.get(pk=project_id) candidate = Candidate.objects.create(answer=answer, project=project) return HttpResponseRedirect(reverse('projects:detail', args=[project_id])) def sort_candidates(request): if request.is_ajax(): items = request.POST.getlist('items[]') i = 1 for item in items: candidate = Candidate.objects.get(pk=item) candidate.position = i candidate.save() i += 1 data = { 'success': 'ok', } return HttpResponse(json.dumps(data), content_type='application/json') class OfferOrderView(View): template_name = 'chattest.html' def get(self, request, *args, **kwargs): return render(request, self.template_name) def contractor_portfolio_create(request): if request.is_ajax(): form = PortfolioForm(data=request.POST) # import code; code.interact(local=dict(globals(), **locals())) if form.is_valid(): duplicate = form.cleaned_data.get('duplicate') instance = form.save(commit=False) instance.user = request.user instance.save() if duplicate: work_sell = WorkSell() work_sell.name = instance.name work_sell.budget = instance.budget work_sell.building_classification = instance.building_classification work_sell.construction_type = instance.construction_type work_sell.currency = instance.currency work_sell.description = instance.description work_sell.term = instance.term work_sell.term_type = instance.term_type work_sell.contractor = instance.user work_sell.save() images_ids = request.POST.get('images-ids').split(';')[:-1] for pk in images_ids: picture = Picture.objects.get(pk=pk) temp_file = ContentFile(picture.file.read()) temp_file.name = picture.file.name p_photo = PortfolioPhoto() p_photo.img = temp_file p_photo.portfolio = instance p_photo.save() if duplicate: w_photo = WorkSellPhoto() w_photo.img = temp_file w_photo.worksell = work_sell w_photo.save() data = {'status': 'ok'} else: data = {'status': 'no', 'form_errors': form.errors} return HttpResponse(json.dumps(data), content_type='application/json') else: raise Http404 class ContractorPortfolioUpdateView(UpdateView): model = Portfolio form_class = PortfolioForm template_name = 'contractor_portfolio_edit.html' def get_success_url(self): return reverse('users:contractor-profile',kwargs={'pk':self.object.user_id}) class PortfolioDelete(DeleteView): model = Portfolio success_url = reverse_lazy('users:contractor-profile') # import code; code.interact(local=dict(globals(), **locals()))