import json from abc import ABC from pprint import pformat import pydash as _ from django.conf import settings from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.core.exceptions import PermissionDenied 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, Count, Sum from django.http import HttpResponseForbidden, JsonResponse, HttpResponseRedirect, HttpResponse, Http404 from django.shortcuts import render, get_object_or_404, redirect from django.views.generic import DetailView, CreateView, DeleteView, View, UpdateView, TemplateView from hitcount.models import HitCount from hitcount.views import HitCountMixin import re from archilance import util from archilance.mixins import BaseMixin from common.mixins import NoCsrfMixin from users.models import User, Team from work_sell.models import Picture, WorkSell, WorkSellPhoto from ratings.models import HistoryRating from .models import ( Answer, AnswerFile, AnswerMessage, Arbitration, BuildingClassfication, Candidate, Order, Portfolio, PortfolioPhoto, Project, ProjectFile, TERM_TYPE_MORPHS, Realty ) from .forms import ( ContractorPortfolioTrashForm, CustomerProjectDeleteForm, CustomerProjectEditForm, CustomerProjectEditFormNew, CustomerProjectRestoreForm, CustomerProjectTrashForm, PortfolioEditForm, PortfolioForm, ProjectAnswerForm, ProjectAnswerMessageForm, ProjectWorkTypeSuggestionForm, RealtyForm, RealtyFormNew ) from specializations.models import Specialization from common.models import Location from common.forms import CustomRegistrationForm _.map = _.map_ _.filter = _.filter_ 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)) context.update({'TERM_TYPE_MORPHS': TERM_TYPE_MORPHS}) project = get_object_or_404(Project, pk=kwargs.get('pk')) context.update({'project': project}) hit_count = HitCount.objects.get_for_object(project) HitCountMixin.hit_count(request, hit_count) if request.user.is_authenticated() and request.user.is_contractor(): project_answers = project.answers.filter(rejected=False) contractor = request.user answer = _.first(_.filter(project_answers, lambda a: a.author == contractor)) if not answer: team = util.get_related_or_none(contractor, 'team') if team: answer = _.first(_.filter(project_answers, lambda a: a.author == team)) context.update({'answer': answer}) # answer.messages.update() if not answer: team = util.get_related_or_none(contractor, 'team') if team: context.update({'can_answer_as_team': True}) 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): # @Отклик на Проект(Project) 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 # Check for duplicate answers: if answer_as_team and util.has_related(request.user, 'team'): if project.answers.filter(object_id=request.user.team.pk, content_type__model='team').exists(): raise PermissionDenied('Повторный отклик') else: if project.answers.filter(object_id=request.user.pk, content_type__model='user').exists(): raise PermissionDenied('Повторный отклик') 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) # FIXME: еще раз находим проект? 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: raise PermissionDenied 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: raise PermissionDenied def post(self, request, *args, **kwargs): form = self.form_class(request.POST, request=request) answer = get_object_or_404(Answer, pk=kwargs.get('pk')) if form.is_valid(): message = form.save(commit=False) if request.user.is_contractor(): 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): team = util.get_related_or_none(request.user, 'team') if team and answer.author == team: message.contractor_or_team = team elif request.user.is_customer(): 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 RejectProjectAnswerView(NoCsrfMixin, LoginRequiredMixin, BaseMixin, View): def post(self, request, *args, **kwargs): if request.user.is_contractor(): answer = None contractor_answer = util.get_or_none(request.user.contractor_answers, pk=kwargs.get('pk')) if contractor_answer: answer = contractor_answer elif request.user.team: answer = util.get_or_none(request.user.team.answers, pk=kwargs.get('pk')) if not answer: raise Http404 elif request.user.is_customer(): project = get_object_or_404(request.user.customer_projects, answers__pk=kwargs.get('pk')) answer = get_object_or_404(project.answers, pk=kwargs.get('pk')) answer.rejected = True answer.save() candidate = Candidate.objects.filter(answer=answer) if candidate: candidate.delete() messages.info(request, 'Успешный отказ от проекта') redirect_to = request.POST.get('next') return redirect(redirect_to) class RestoreProjectAnswerView(NoCsrfMixin, LoginRequiredMixin, BaseMixin, View): def post(self, request, *args, **kwargs): if request.user.is_contractor(): answer = None contractor_answer = util.get_or_none(request.user.contractor_answers, pk=kwargs.get('pk')) if contractor_answer: answer = contractor_answer elif request.user.team: answer = util.get_or_none(request.user.team.answers, pk=kwargs.get('pk')) if not answer: raise Http404 elif request.user.is_customer(): project = get_object_or_404(request.user.customer_projects, answers__pk=kwargs.get('pk')) answer = get_object_or_404(project.answers, pk=kwargs.get('pk')) answer.rejected = False answer.save() messages.info(request, 'Проект успешно восстановлен') redirect_to = request.POST.get('next') return redirect(redirect_to) def build_query(id_str, _class, *args): query = Q() id_list = tuple(filter(None, re.split(r'\s|,|;', id_str))) for id in id_list: obj = _class.objects.get(id=id) kwargs = dict(zip(args, (obj.lft, obj.rght))) query |= Q(**kwargs) return query class ProjectFilterView(BaseMixin, View): template_name = 'project_filter.html' # form_class = ProjectFilterForm # renderer_classes = (TemplateHTMLRenderer,) PROJECT_ORDER_CHOICES = ( # "Упорядочить по"... ('name', 'названию'), ('budget', 'цене'), ('created', 'дате размещения'), ('views', 'просмотрам'), ) def filter(self, projects, data): # print("filter data = ", data) specialization = data.get('specialization') keywords = data.get('keywords') building_classification = data.get('building_classification') construction_type = data.get('construction_type') location = data.get('location') cro = data.get('cro') if keywords: # print("keywords = ", keywords) keywords = tuple(filter(None, re.split(r'\s|,|;', keywords))) for k in keywords: projects = projects.filter(Q(name__icontains=k.lower()) | Q(text__icontains=k.lower())) if specialization: query = build_query(specialization, Specialization, 'specialization__lft__gte', 'specialization__rght__lte') projects = projects.filter(query) if building_classification: query = build_query(building_classification, BuildingClassfication, 'realty__building_classification__lft__gte', 'realty__building_classification__rght__lte') projects = projects.filter(query) if construction_type: projects = projects.filter(realty__construction_type__in= tuple(filter(None, re.split(r'\s|,|;', construction_type)))) if location: query = build_query(location, Location, 'realty__location__lft__gte', 'realty__location__rght__lte') projects = projects.filter(query) if cro: projects = projects.filter(cro=True) return projects def sort_by(self, projects): # order_by = request.GET.get('order_by') # last_order_by = request.GET.get('last_order_by') # reverse_order = request.GET.get('reverse_order') # ord = None # manual_sort = None # # # ORDERS # 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 and ord == 'views': # projects = natsort.natsorted(projects.all(), key=lambda p: p.hit_count.hits, reverse=reverse_order) # manual_sort = True # elif ord: # projects = projects.order_by('-%s' % ord if reverse_order else ord) return projects def pagination(self, projects, page): paginator = Paginator(projects, settings.PAGE_SIZE) # print("pag page = ", page) try: projects = paginator.page(page) except PageNotAnInteger: projects = paginator.page(1) except EmptyPage: projects = paginator.page(paginator.num_pages) return projects def get_context(self, request): context = request.dict() projects = Project.objects.filter(state='active', order__status='created') projects = self.filter(projects, request) num_results = projects.count() projects = self.sort_by(projects) projects = self.pagination(projects, request.get("page")) has_additional_fields = bool(context.get("building_classification") or context.get( "construction_type") or context.get("location") or context.get("cro")) context.update({ 'choices': self.PROJECT_ORDER_CHOICES, 'projects': projects, 'is_paginated': True, 'page_obj': projects, 'num_results': num_results, 'has_additional_fields': has_additional_fields }) return context def get(self, request): return render(request, self.template_name, self.get_context(request.GET)) def post(self, request): return render(request, 'partials/inc-projects-results.html', self.get_context(request.POST)) class SortRealtyBy(View): def get_context(self): print("request.POST = ", self.request.POST) user_id = self.request.POST.get('user_id') sort_by = self.request.POST.get('sortBy') state = self.request.POST.get('state') objects = Realty.objects.filter(user__id=user_id, state=state, is_virtual=False) if sort_by == 'num_orders': objects = objects.annotate(num_orders=Count('projects')) return {"objects": objects.order_by('{}'.format(sort_by))} def post(self, *args, **kwargs): return render(self.request, 'partials/inc-objects.html', self.get_context()) class CustomerProjectCreateView(BaseMixin, View): form_class = CustomerProjectEditFormNew realty_form = RealtyFormNew work_type_suggestion_form = ProjectWorkTypeSuggestionForm template_name = 'customer_project_create.html' def get_context_data(self, **kwargs): ctx = super().get_context_data() # ctx['hide_user_type'] = False user_form = CustomRegistrationForm() ctx['user_form'] = user_form return ctx def get(self, request, *args, **kwargs): context = self.get_context_data(**_.merge({}, request.GET, kwargs)) form = self.form_class(request=request) realty_form = self.realty_form(request=request, prefix='realty_form') work_type_suggestion_form = self.work_type_suggestion_form(request=request, prefix='work_type_suggestion') context.update({ 'form': form, 'realty_form': realty_form, 'work_type_suggestion_form': work_type_suggestion_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 print('POST = ', request.POST) form.is_valid() realty = form.cleaned_data.get('realty') if realty: print("Has Realty") realty_form = self.realty_form(request.POST, instance=realty, request=request, prefix='realty_form') else: print("Create new Realty") 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) unregister_user = request.POST.get('not_auth_user_id') if unregister_user: user = get_object_or_404(User, pk=unregister_user) else: user = request.user project.customer = user project.save() form.save_m2m() Order.objects.create(project=project, secure=project.deal_type == 'secure_deal') for file in request.FILES.getlist('new_files'): ProjectFile.objects.create(file=file, project=project) if not realty: realty = realty_form.save(commit=False) realty.user = user if not request.POST.get('new_realty_name'): print("Virtual!") realty.is_virtual = True print("Set realty name -->", request.POST.get('new_realty_name')) realty.name = request.POST.get('new_realty_name') 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}) unregister_user = request.POST.get('not_auth_user_id') if unregister_user: context.update({'unregister_user': unregister_user}) return render(request, self.template_name, context) class CustomerProjectEditView(BaseMixin, View): form_class = CustomerProjectEditForm realty_form = RealtyForm work_type_suggestion_form = ProjectWorkTypeSuggestionForm template_name = 'customer_project_edit.html' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): # Prevent editing when project's taken: project = get_object_or_404(request.user.customer_projects, pk=kwargs.get('pk')) if project.order.contractor or project.order.team: raise PermissionDenied('Заказ уже находится в работе. Вы не можете его редактировать.') else: return super().dispatch(request, *args, **kwargs) raise PermissionDenied def get(self, request, *args, **kwargs): project = get_object_or_404(request.user.customer_projects, pk=kwargs.get('pk')) form = self.form_class(instance=project, request=request) work_type_suggestion_form = self.work_type_suggestion_form(request=request, prefix='work_type_suggestion') 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, 'work_type_suggestion_form': work_type_suggestion_form, }) return render(request, self.template_name, context) def post(self, request, *args, **kwargs): project = get_object_or_404(request.user.customer_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(): # Prevent editing when project's taken: project = get_object_or_404(request.user.customer_projects, pk=kwargs.get('pk')) if project.order.contractor or project.order.team: raise PermissionDenied('Заказ уже находится в работе. Вы не можете его переместить в корзину.') else: return super().dispatch(request, *args, **kwargs) raise PermissionDenied 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 AbcCustomerRealityChangeState(ABC, View): new_state = '' message_part = '' def __init__(self, **kwargs): if self.new_state not in [el[0] for el in Realty.STATES]: raise AttributeError('new_state must be in {}'.format([el[0] for el in Realty.STATES])) super().__init__(**kwargs) # TODO: dispatch вынести в ABC класс # def dispatch(self, request, *args, **kwargs): def post(self, request, *args, **kwargs): realty = get_object_or_404(Realty, pk=kwargs.get("pk")) realty.state = self.new_state realty.save() realty.projects.all().update(state=self.new_state) messages.info(request, 'Объект и все, связанные с ним проекты, {}'.format(self.message_part)) redirect_to = request.POST.get('next') return redirect(redirect_to) class CustomerRealtyTrashView(AbcCustomerRealityChangeState): new_state = 'trashed' message_part = 'перемещёны в корзину' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): num_project_in_process = Project.objects.filter(realty__id=kwargs.get('pk')).filter(order__status="process").count() if num_project_in_process: raise PermissionDenied('Один или более Заказ, данного Объекта, уже находятся в работе. ' 'Вы не можете переместить его в корзину.') else: return super().dispatch(request, *args, **kwargs) raise PermissionDenied class CustomerRealtyDeleteView(AbcCustomerRealityChangeState): new_state = 'deleted' message_part = 'удалены' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: raise PermissionDenied class CustomerRealtyRestoreView(AbcCustomerRealityChangeState): new_state = 'active' message_part = 'восстановлены' def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated() and request.user.is_customer(): return super().dispatch(request, *args, **kwargs) else: raise PermissionDenied 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: raise PermissionDenied 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: raise PermissionDenied 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): c = super().get_context_data(**kwargs) c['TERM_TYPE_MORPHS'] = TERM_TYPE_MORPHS return c def add_candidate(request, answer_id, project_id): answer = Answer.objects.get(pk=answer_id) project = Project.objects.get(pk=project_id) count_answers = Candidate.objects.filter(project=project).count() count_answers += 1 candidate = Candidate.objects.filter(answer=answer).first() if not candidate: Candidate.objects.create(answer=answer, project=project, position=count_answers) redirect_to = '%s%s' % (reverse('projects:detail', kwargs={'pk': project_id}), '#answers') return redirect(redirect_to) class CandidateDeleteView(DeleteView): model = Candidate def get_success_url(self): return reverse('projects:comparison', kwargs={'pk': self.object.project_id}) def get(self, *args, **kwargs): return self.post(*args, **kwargs) 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 CustomerOfferOrderView(View): template_name = 'chattest.html' def post(self, request, *args, **kwargs): # @ Утверждение Исполнителя project_id = kwargs.get('project_id') answer_id = kwargs.get('answer_id') try: project = Project.objects.get(pk=project_id) except Project.DoesNotExist: project = None try: answer = Answer.objects.get(pk=answer_id) except Answer.DoesNotExist: answer = None order = project.order status = None if not order.contractor and not order.team: if isinstance(answer.author, User): order.contractor = answer.author # order.status = 'process' # order.save() # status = True elif isinstance(answer.author, Team): order.team = answer.author order.status = 'process' order.save() status = True if status: hs_rating = HistoryRating() hs_rating.user = request.user hs_rating.rating = 1 hs_rating.type = 'choice_contractor' hs_rating.description = 'Заказчик выбрал исполнителя' hs_rating.save() redirect_url = reverse('chat:chat-user') + '#order' + str(order.pk) return HttpResponseRedirect(redirect_url) def contractor_portfolio_create(request): # TODO: pekopt: shit. rewrite using generic 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(BaseMixin, UpdateView): model = Portfolio form_class = PortfolioEditForm template_name = 'contractor_portfolio_edit.html' def get_success_url(self): return reverse('projects:contractor-portfolio-detail', kwargs={'pk': self.object.pk}) def form_valid(self, form): portfolio = form.instance photos = form.cleaned_data['photos'] # # Doesn't work: # # portfolio.photos = photos # portfolio.save() PortfolioPhoto.objects.filter(portfolio=portfolio).delete() for photo in photos: PortfolioPhoto.objects.create(img=photo.img, portfolio=portfolio) live_images = form.cleaned_data['live_images'] for live_image in live_images: new_image = ContentFile(live_image.file.read()) new_image.name = live_image.file.name PortfolioPhoto.objects.create(img=new_image, portfolio=portfolio) live_image.file.delete() live_image.delete() return super().form_valid(form) class PortfolioDelete(DeleteView): model = Portfolio success_url = reverse_lazy('users:contractor-profile') class PortfolioDetail(DetailView): model = Portfolio template_name = 'portfolio_detail.html' def dispatch(self, request, *args, **kwargs): if not self.get_object().user: return HttpResponseForbidden('404 Not Found') return super().dispatch(request, *args, **kwargs) class ArbitrationCreateView(CreateView): model = Arbitration fields = ( 'order', 'user', 'text', ) def form_valid(self, form): if self.request.is_ajax(): self.object = form.save() data = { 'status': 'ok', } return JsonResponse(data) return super().form_valid(form) def form_invalid(self, form): if self.request.is_ajax(): return JsonResponse(form.errors, status=400) return super().form_invalid(form) class ProjectWorkTypeSuggestionView(View): form_class = ProjectWorkTypeSuggestionForm template_name = 'customer_project_work_type_suggestion.html' # def get(self, request, *args, **kwargs): # form = self.form_class(request=request, prefix='work_type_suggestion') # context = {'form': form} # return render(request, self.template_name, context) def post(self, request, *args, **kwargs): form = self.form_class(request.POST, request=request, prefix='work_type_suggestion') if form.is_valid(): form.save() return JsonResponse({'status': 'success'}) else: form_errors = {'.-error-%s' % bfield.html_name: bfield.errors for bfield in form} return JsonResponse({ 'status': 'error', 'form_errors': form_errors, }) # import code; code.interact(local=dict(globals(), **locals()))