import json import re import pydash as _; _.map = _.map_; _.filter = _.filter_ from pprint import pformat from django.shortcuts import render, redirect, get_object_or_404 from django.conf import settings from django.contrib import messages from django.db.models import Q from django.core.urlresolvers import reverse from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.exceptions import PermissionDenied from django.http import JsonResponse, HttpResponse, HttpResponseForbidden from django.core.files.base import ContentFile from django.views.generic import ListView, DetailView, CreateView, View, \ UpdateView, DeleteView, TemplateView from projects.models import BuildingClassfication, ConstructionType from projects.forms import ProjectWorkTypeSuggestionForm from archilance.mixins import BaseMixin from common.forms import CustomRegistrationForm from users.models import User from .models import WorkSell, Picture, WorkSellPhoto, WorkSellPhoto from .forms import WorkSellForm, WorkSellFilterForm, ContractorWorkSellTrashForm from .serialize import serialize from .response import JSONResponse, response_mimetype from specializations.models import Specialization from common.models import Location from archilance import util class PictureCreateView(CreateView): model = Picture fields = '__all__' def form_valid(self, form): self.object = form.save() files = [serialize(self.object)] data = {'files': files} response = JSONResponse(data, mimetype=response_mimetype(self.request)) response['Content-Disposition'] = 'inline; filename=files.json' return response def form_invalid(self, form): data = json.dumps(form.errors) return HttpResponse(content=data, status=400, content_type='application/json') class BasicCreateView(PictureCreateView): template_name = 'picture_basic_form.html' class WorkSellsView(ListView): model = WorkSell template_name = 'worksells_list.html' # paginate_by = 20 paginate_by = 18 def get_form_kwargs(self, **kwargs): kwargs = super().get_form_kwargs def get_queryset(self, **kwargs): qs = WorkSell.objects.all() # if self.request.GET: # budget_from = self.request.GET # pass return qs def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['building_classifications'] = BuildingClassfication.objects.all() context['construction_types'] = ConstructionType.objects.all() return context class WorkSellFilterView(BaseMixin, View): template_name = 'worksell_filter.html' # form_class = WorkSellFilterForm include_template = 'partials/inc-worksell-results.html' PROJECT_ORDER_CHOICES = ( # "Упорядочить по"... ('name', 'названию'), ('budget', 'цене'), ) def set_filter(self, objects, request_data): specialization = request_data.get('specialization') keywords = request_data.get('keywords') building_classification = request_data.get('building_classification') construction_type = request_data.get('construction_type') location = request_data.get('location') el_format = request_data.get('el_format') if keywords: keywords = tuple(filter(None, re.split(r'\s|,|;', keywords))) for k in keywords: objects = objects.filter(Q(name__icontains=k.lower()) | Q(description__icontains=k.lower())) if specialization: query = util.build_query(specialization, Specialization, 'specializations__lft__gte', 'specializations__rght__lte') objects = objects.filter(query) if building_classification: query = util.build_query(building_classification, BuildingClassfication, 'building_classification__lft__gte', 'building_classification__rght__lte') objects = objects.filter(query) # if construction_type: objects = objects.filter(construction_type__in= tuple(filter(None, re.split(r'\s|,|;', construction_type)))) if location: query = util.build_query(location, Location, 'location__lft__gte', 'location__rght__lte') objects = objects.filter(query) if el_format: objects = objects.exclude(el_format=None) return objects def sort_by(self, objects, order_by): if not order_by: return objects return objects.order_by(order_by) def pagination(self, objects, page): paginator = Paginator(objects, settings.PAGE_SIZE) try: objects = paginator.page(page) except PageNotAnInteger: objects = paginator.page(1) except EmptyPage: objects = paginator.page(paginator.num_pages) return objects def get_context(self, request): context = request.dict() worksells = WorkSell.objects.all() worksells = self.set_filter(worksells, request) num_results = worksells.count() worksells = self.sort_by(worksells, request.get("order_by")) worksells = self.pagination(worksells, request.get("page")) has_additional_fields = bool(context.get("building_classification") or context.get( "construction_type") or context.get("location") or context.get("cro")) display_msg = 'Найдено %s проектов' % num_results if num_results > 0 else 'Ничего не найдено' context.update({ 'choices': self.PROJECT_ORDER_CHOICES, 'worksells': worksells, 'is_paginated': True, 'display_msg': display_msg, 'page_obj': worksells, '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, self.include_template, self.get_context(request.POST)) class WorkSellDetail(DetailView): model = WorkSell template_name = 'worksell_detail.html' def dispatch(self, request, *args, **kwargs): if not self.get_object().contractor and not self.get_object().team: return HttpResponseForbidden('404 Not Found') return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Своя собственная Работа self_worksell = False try: if self.get_object().id in [obj.id for obj in self.request.user.work_sell.all()]: self_worksell = True except AttributeError: pass context['worksell_related'] = WorkSell.objects.exclude(pk=self.get_object().pk)[:5] context['self_worksell'] = self_worksell return context class WorkSellCreateView(BaseMixin, View): model = WorkSell form_class = WorkSellForm work_type_suggestion_form = ProjectWorkTypeSuggestionForm template_name = 'worksell_create.html' # Пускаем всех, т.к. незарегистрированный пользователь должен иметь возможность "Создать проект" # def dispatch(self, request, *args, **kwargs): # if request.user.is_authenticated() and request.user.is_contractor(): # return super().dispatch(request, *args, **kwargs) # else: # raise PermissionDenied def get_context_data(self, **kwargs): ctx = super().get_context_data() 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) work_type_suggestion_form = self.work_type_suggestion_form(request=request, prefix='work_type_suggestion') context.update({ 'form': form, 'work_type_suggestion_form': work_type_suggestion_form, }) return render(request, self.template_name, context) def post(self, request, *args, **kwargs): # print("request.POST = ", request.POST) # print("files = ", request.FILES.getlist('new_files')) request.POST = request.POST.copy() # Если фронт не будет возвращать пустую строку при незаполненных данных, то if'ы будут не нужны if request.POST.get('specializations') == "": print("POP") request.POST.pop('specializations') else: request.POST.setlist('specializations', request.POST.get('specializations', "").split(',')) if request.POST.get('el_format') == "": request.POST.pop('el_format') else: request.POST.setlist('el_format', request.POST.get('el_format', "").split(',')) form = self.form_class(request.POST, request=request) if form.is_valid(): work_sell = 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 work_sell.contractor = user work_sell.save() form.save_m2m() for file, desc in zip(request.FILES.getlist('new_files'), request.POST.getlist('img_description')): WorkSellPhoto.objects.create(img=file, description=desc, worksell=work_sell) redirect_to = reverse('work_sell:detail', kwargs={'pk': work_sell.pk}) if request.is_ajax(): return JsonResponse({'redirect_to': redirect_to}, status=200) messages.info(request, 'Работа успешно создана') return redirect(redirect_to) else: if form.errors: messages.info(request, ( '

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

' '
{form}
' ).format(form=pformat(form.errors))) context = self.get_context_data(**kwargs) context.update({'form': form}) if request.is_ajax(): data = json.dumps(form.errors) return HttpResponse(content=data, status=400, content_type='application/json') return render(request, self.template_name, context) class WorkSellUpdateView(UpdateView): model = WorkSell form_class = WorkSellForm template_name = 'worksell_edit.html' def dispatch(self, request, *args, **kwargs): if self.get_object().contractor_id != request.user.pk: return HttpResponseForbidden('403 Forbidden') return super().dispatch(request, *args, **kwargs) def get_success_url(self): return reverse('work_sell:detail', kwargs={'pk': self.object.pk}) def form_valid(self, form): worksell = form.instance photos = form.cleaned_data['photos'] WorkSellPhoto.objects.filter(worksell=worksell).delete() for photo in photos: WorkSellPhoto.objects.create(img=photo.img, worksell=worksell) 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 WorkSellPhoto.objects.create(img=new_image, worksell=worksell) live_image.file.delete() live_image.delete() return super().form_valid(form) class WorkSellDeleteView(DeleteView): model = WorkSell template_name = 'worksell_delete.html' def get_success_url(self): return reverse('work_sell:filter') class ContractorWorkSellTrashView(View): form_class = ContractorWorkSellTrashForm def post(self, request, *args, **kwargs): form = self.form_class(_.merge({}, request.POST, kwargs), request=request) if form.is_valid(): worksell = form.cleaned_data.get('pk') worksell.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 UploadView(View): template_name = 'upload.html' def get(self, request, *args, **kwargs): return render(request, self.template_name) class JSONResponseMixin(object): def render_to_json_response(self, context, **response_kwargs): return JsonResponse( self.get_data(context), **response_kwargs ) def get_data(self, context): context = {'test': 'data'} return context class JSONView(JSONResponseMixin, TemplateView): def render_to_response(self, context, **response_kwargs): return self.render_to_json_response(context, **response_kwargs)