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.
 
 
 
 
 
 

530 lines
18 KiB

# -*- coding: utf-8 -*-
import random
from accounts.models import User
from city.models import City
from company.models import Company
from conference.models import Conference
from country.models import Country
from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
from django.core.context_processors import csrf
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.core.paginator import (
EmptyPage,
InvalidPage,
PageNotAnInteger,
Paginator
)
from django.core.urlresolvers import reverse_lazy
from django.db.models.deletion import ProtectedError
from django.db.models.loading import get_model
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.utils.translation import get_language as lang
from django.utils.translation import ugettext as _
from django.views.generic import ListView as OldListView
from django.views.generic import DetailView, RedirectView
from django.views.generic.detail import (
SingleObjectMixin,
SingleObjectTemplateResponseMixin
)
from django.views.generic.edit import ModelFormMixin, ProcessFormView
from exposition.models import Exposition
from file.forms import FileModelForm
from file.models import TmpFile
from functions.forms import AdminSearchForm
from functions.views_help import split_params
from haystack.query import EmptySearchQuerySet
from hvad.utils import get_translation_aware_manager
from meta.models import MetaSetting
from meta.views import Meta
from photoreport.models import Photoreport
from seminar.models import Seminar
from theme.models import Tag, Theme
from webinar.models import Webinar
class ListView(OldListView):
"""
Default Django generic ListView with few overrided methods for redirecting
onto first page of pagination in case of entering big page number(for search engines)
List of modules, where overrided ListView is used:
- accounts.views
- article.views
- company.views
- conference.views
- core.views
- exposition.views
- photologue.views
- place_exposition.views
- specialist_catalog.views
- translator.views
"""
def paginate_queryset(self, queryset, page_size):
"""
Paginate the queryset, if needed.
"""
paginator = self.get_paginator(queryset, page_size, allow_empty_first_page=self.get_allow_empty())
page_kwarg = self.page_kwarg
page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
try:
page_number = int(page)
except ValueError:
if page == 'last':
page_number = paginator.num_pages
else:
raise Http404(_("Page is not 'last', nor can it be converted to an int."))
try:
page = paginator.page(page_number)
self.kwargs['home'] = False
except EmptyPage as e:
page = paginator.page(1)
self.kwargs['home'] = True
return (paginator, page, page.object_list, page.has_other_pages())
def get(self, request, *args, **kwargs):
response = super(ListView, self).get(request, *args, **kwargs)
if self.kwargs.get("home"):
path = self.request.path
return HttpResponseRedirect(path[:path.find('page')])
else:
return response
@login_required
def filtered_list(request, objects, template, item_per_page=settings.ADMIN_PAGINATION):
"""
Return template with objects in it with pagination
item_per_page - how many objects view in the one page
"""
paginator = Paginator(objects, item_per_page)
page = request.GET.get('page')
try:
objects = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
objects = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
objects = paginator.page(paginator._num_pages)
return render_to_response(template, {'objects': objects, 'search_form': AdminSearchForm()})
@staff_member_required
def objects_list(request, Model, template, item_per_page=settings.ADMIN_PAGINATION):
"""
Return template with all objects of model Model
Model - objects Model
item_per_page - how many objects view in the one page
"""
if request.GET:
form = AdminSearchForm(request.POST)
if form.is_valid():
s_name = request.GET.get('search_name')
if s_name:
objects = get_translation_aware_manager(Model).filter(name__contains=s_name).distinct()
return filtered_list(request, objects, template, 1000)
else:
list = Model.objects.all()
else:
list = Model.objects.all()
paginator = Paginator(list, item_per_page)
page = request.GET.get('page')
try:
objects = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
objects = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
objects = paginator.page(paginator._num_pages)
return render_to_response(template, {'objects': objects, 'search_form': AdminSearchForm()})
@login_required
def add_object(request, Form, template_string, redirect_string, #required values
choices={}, init_data ={}):
if request.POST:
form = Form(request.POST)
#set choices filled by ajax
if 'city' in choices:
form.fields['city'].choices = [(item.id, item.name) for item in choices['city'].objects.filter(country=request.POST['country'])]
if 'tag' in choices:
form.fields['tag'].choices = [(item.id, item.name) for item in choices['tag'].objects.all()]
if form.is_valid():
form.save()
return HttpResponseRedirect(redirect_string)
else:
form = Form(initial=init_data)
args = {}
args.update(csrf(request))
args['languages'] = settings.LANGUAGES
args['form'] = form
return render_to_response(template_string, args)
@login_required
def add_object_with_file(request, Form, template, redirect_string, #required values
choices={}, init_data ={}):
"""
Return form and FileForm and post it on the server.
Create key which will be check tmp files
If form is posted redirect on the page in redirect_string
FileForm posts with ajax
choices are ...
"""
#cheks if key already exist(when form wasn't validated)
if request.POST.get('key'):
key = request.POST['key']
else:
key = random.getrandbits(128)
#initial FileForm with key for checking if file connected to object
file_form = FileModelForm(initial={'key': key})
if request.POST:
form = Form(request.POST)
#set choices filled by ajax
if 'city' in choices:
form.fields['city'].choices = [(item.id, item.name) for item in choices['city'].objects.filter(country=request.POST['country'])]
if 'tag' in choices:
form.fields['tag'].choices = [(item.id, item.name) for item in Tag.objects.all()]
if form.is_valid():
form.save()
return HttpResponseRedirect(redirect_string)
else:
init_data['key'] = key
form = Form(initial=init_data)
args = {}
args.update(csrf(request))
#languages uses in template
args['languages'] = settings.LANGUAGES
args['form'] = form
args['file_form'] = file_form
#list of files connected to this form
args['files'] = TmpFile.objects.filter(key=key)
return render_to_response(template, args)
@login_required
def delete_object(request, Model, Form, url, prev_page,):
"""
Form must have 1 parameter url or id
"""
if request.GET:
url = request.GET.get('url')
id = request.GET.get('id')
if url:
object = Model.objects.get(url=url)
else:
object = Model.objects.get(id=id)
try:
object.delete()
return HttpResponseRedirect(prev_page)
except ProtectedError:
msg = _(u'Удаления %(object)s требует удаления связаных объектов') % {'object': object}
return render_to_response('delete.html', {'msg':msg, 'prev_page':prev_page})
else:
try:
object = Model.objects.get(url=url)
except:
object = Model.objects.get(id=url)
form = Form(instance=object)
args = {}
args.update(csrf(request))
args['form'] = form
args['object'] = object
args['prev_page'] = prev_page
return render_to_response('delete.html', args)
class ExpoMixin(object):
def get_params(self):
model_names = {Exposition: _(u'Выставки'), Conference: _(u'Конференции'), Seminar: _(u'Семинары'),
Webinar: _(u'Вебинары'), Company: _(u'Участники'), Photoreport: _(u'Фоторепортажи')}
model_alternative_name = {Exposition: 'exposition', Conference: 'conference', Photoreport: 'photoreport'}
params = [{'type':'model', 'url':self.model, 'name': model_names.get(self.model),
'alternative_name': model_alternative_name.get(self.model)}]
st = self.kwargs.get('params')
if st:
params = params + split_params(st)
return params
single_page_filter = {Exposition:'event', Conference:'event', Seminar:'event', Webinar:'event', Company:'member',
User:'visitor', Photoreport: 'photoreport'}
class ExpoListView(ExpoMixin, ListView):
"""
"""
paginate_by = settings.CLIENT_PAGINATION
params = None
single_page = False
search_form = None
order = None
def get_queryset(self):
query = self.model.objects.all()
params = self.get_params()
for param in params:
if param.get('type') == 'country':
country = Country.objects.safe_get(url=param.get('url'))
if country:
param['name'] = country.name
query = query.filter(country=country)
if param.get('type') == 'city':
city = City.objects.safe_get(url=param.get('url'))
if city:
param['name'] = city.name
query = query.filter(city=city)
if param.get('type') == 'theme':
theme = Theme.objects.safe_get(url=param.get('url'))
if theme:
param['name'] = theme.name
query = query.filter(theme=theme)
if param.get('type') == 'tag':
tag = Tag.objects.safe_get(url=param.get('url'))
if tag:
param['name'] = tag.name
query = query.filter(tag=tag)
if param.get('type') == 'year':
param['name'] = param.get('url')
query = query.filter(data_begin__year=param.get('url'))
if param.get('type') == 'month':
monthes = {'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4, 'may': 5, 'jun': 6,
'jul': 7, 'aug': 8, 'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12}
param['name'] = param.get('url')
query = query.filter(data_begin__month=monthes.get(param.get('url')))
if param.get('type') == 'member' and self.model != Company:
param['name'] = param.get('url')
company = Company.objects.safe_get(url=param.get('url'))
if company:
param['name'] = company.name
query = query.filter(company__in=[company])
if param.get('type') == single_page_filter.get(self.model):
query = query.filter(url=param.get('url'))
if query:
self.single_page = True
param['name'] = query[0].name
#if self.request:
# views = query[0].views
# query.update(views=views+1)
self.params = params
if self.order:
return query.order_by(self.order)
else:
return query
def get_context_data(self, **kwargs):
context = super(ExpoListView, self).get_context_data(**kwargs)
context['filter'] = self.params
context['single_page'] = self.single_page
context['search_form'] = self.search_form
if self.single_page:
s = MetaSetting.objects.get(name='expo')
obj = context['object_list'][0]
params = s.generate_meta(obj)
m = Meta(**params)
context['meta'] = m
return context
class EventDetail(ExpoMixin, DetailView):
def get_object(self, queryset=None):
obj = Country.objects.filter()[0]
return obj
class ExpoSearchView(ListView):
paginate_by = settings.CLIENT_PAGINATION
template_name = None
search_form = None
model = None
def get_queryset(self):
if self.request.GET:
form = self.search_form(self.request.GET)
if form.is_valid():
return form.search()
else:
return EmptySearchQuerySet()
else:
return EmptySearchQuerySet()
def get_context_data(self, **kwargs):
context = super(ExpoSearchView, self).get_context_data(**kwargs)
if self.request.GET:
form = self.search_form(self.request.GET)
if form.is_valid():
form.data_with_parents = form.get_form_data()
else:
form = self.search_form()
context['search_form'] = form
queries = self.request.GET.copy()
if queries.has_key('page'):
del queries['page']
context['queries'] = queries
return context
class SimpleObjectChangeView(RedirectView, SingleObjectMixin):
model = None
url = None
slug_field = 'url'
slug_url_kwarg = 'url'
attr = None
attr_state = None
query_string = True
def get_object(self, queryset=None):
"""
Returns the object the view is displaying.
By default this requires `self.queryset` and a `pk` or `slug` argument
in the URLconf, but subclasses can override this to return any object.
"""
# Use a custom queryset if provided; this is required for subclasses
# like DateDetailView
if queryset is None:
queryset = self.get_queryset()
qs = self.model._default_manager.none()
# Next, try looking up by url or primary key.
slug = self.kwargs.get(self.slug_url_kwarg, None)
if slug is not None:
slug_field = self.get_slug_field()
qs = queryset.filter(**{slug_field: slug})
if not qs:
qs = queryset.filter(pk=slug)
# If none of those are defined, it's an error.
else:
raise AttributeError("Generic detail view %s must be called with "
"either an object pk or a slug."
% self.__class__.__name__)
try:
# Get the single item from the filtered queryset
obj = qs.get()
except ObjectDoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': qs.model._meta.verbose_name})
return obj
def change_object(self, **kwargs):
setattr(self.object, self.attr, self.attr_state)
self.object.save(update_fields=[self.attr])
def get(self, request, *args, **kwargs):
self.object = self.get_object()
self.change_object()
print(self.request.META.get('QUERY_STRING', ''))
return super(SimpleObjectChangeView, self).get(request, *args, **kwargs)
class BlockedFilterMixin(object):
'''Filters default queryset with excluding blocked items
'''
def get_queryset(self):
qs = super(BlockedFilterMixin, self).get_queryset()
return qs.filter(blocked=False)
class AjaxableResponseMixin(object):
"""
Mixin to add AJAX support to a form.
Must be used with an object-based FormView (e.g. CreateView)
"""
def form_invalid(self, form):
response = super(AjaxableResponseMixin, self).form_invalid(form)
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
else:
return response
def form_valid(self, form):
# We make sure to call the parent's form_valid() method because
# it might do some processing (in the case of CreateView, it will
# call form.save() for example).
response = super(AjaxableResponseMixin, self).form_valid(form)
if self.request.is_ajax():
data = {
'pk': self.object.pk,
}
return JsonResponse(data)
else:
return response
class CreateUpdateView(SingleObjectTemplateResponseMixin, ModelFormMixin, ProcessFormView):
def get_object(self, queryset=None):
try:
return super(CreateUpdateView,self).get_object(queryset)
except AttributeError:
return None
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super(CreateUpdateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super(CreateUpdateView, self).post(request, *args, **kwargs)
class ContextMixin(object):
initial_ctx = {}
def dispatch(self, request, *args, **kwargs):
self.extra_ctx = self.initial_ctx.copy()
return super(ContextMixin, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(ContextMixin, self).get_context_data(**kwargs)
context.update(self.extra_ctx)
return context