You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
355 lines
13 KiB
355 lines
13 KiB
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
|
|
if self.get_object().id in [obj.id for obj in self.request.user.work_sell.all()]:
|
|
self_worksell = True
|
|
|
|
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, (
|
|
'<p>Произошла ошибка (form)</p>'
|
|
'<pre>{form}</pre>'
|
|
).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, 'Произошла ошибка: <pre>{msg}</pre>'.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)
|
|
|