X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/57e98a5807465f9494e5006e16860f16abbf4136..6280673f35e13e75e81c5b7821bd2a44a1831eab:/apps/ajaxable/utils.py diff --git a/apps/ajaxable/utils.py b/apps/ajaxable/utils.py index ac8d5c6f9..89b56228d 100755 --- a/apps/ajaxable/utils.py +++ b/apps/ajaxable/utils.py @@ -1,34 +1,28 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# from functools import wraps from django.http import (HttpResponse, HttpResponseRedirect, HttpResponseForbidden) from django.shortcuts import render_to_response from django.template import RequestContext -from django.utils.cache import patch_vary_headers from django.utils.encoding import force_unicode from django.utils.functional import Promise from django.utils.http import urlquote_plus -from django.utils import simplejson +import json from django.utils.translation import ugettext_lazy as _ from django.views.decorators.vary import vary_on_headers +from honeypot.decorators import verify_honeypot_value -class LazyEncoder(simplejson.JSONEncoder): +class LazyEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, Promise): return force_unicode(obj) return obj -# shortcut for JSON reponses -class JSONResponse(HttpResponse): - def __init__(self, data={}, callback=None, **kwargs): - # get rid of mimetype - kwargs.pop('mimetype', None) - data = simplejson.dumps(data) - if callback: - data = callback + "(" + data + ");" - super(JSONResponse, self).__init__(data, mimetype="application/json", **kwargs) - def method_decorator(function_decorator): """Converts a function decorator to a method decorator. @@ -70,23 +64,29 @@ class AjaxableFormView(object): # override to customize form look template = "ajaxable/form.html" submit = _('Send') - + title = '' success_message = '' POST_login = False formname = "form" form_prefix = None full_template = "ajaxable/form_on_page.html" + honeypot = False @method_decorator(vary_on_headers('X-Requested-With')) def __call__(self, request, *args, **kwargs): """A view displaying a form, or JSON if request is AJAX.""" - #form_class = placeholdized(self.form_class) if self.placeholdize else self.form_class - form_args, form_kwargs = self.form_args(request, *args, **kwargs) + obj = self.get_object(request, *args, **kwargs) + form_args, form_kwargs = self.form_args(request, obj) if self.form_prefix: form_kwargs['prefix'] = self.form_prefix if request.method == "POST": + if self.honeypot: + response = verify_honeypot_value(request, None) + if response: + return response + # do I need to be logged in? if self.POST_login and not request.user.is_authenticated(): return require_login(request) @@ -95,14 +95,16 @@ class AjaxableFormView(object): form = self.form_class(*form_args, **form_kwargs) if form.is_valid(): add_args = self.success(form, request) - redirect = request.GET.get('next') - if not request.is_ajax() and redirect: - return HttpResponseRedirect(urlquote_plus( - redirect, safe='/?=&')) - response_data = {'success': True, - 'message': self.success_message, 'redirect': redirect} + response_data = { + 'success': True, + 'message': self.success_message, + 'redirect': request.GET.get('next') + } if add_args: response_data.update(add_args) + if not request.is_ajax() and response_data['redirect']: + return HttpResponseRedirect(urlquote_plus( + response_data['redirect'], safe='/?=&')) elif request.is_ajax(): # Form was sent with errors. Send them back. if self.form_prefix: @@ -124,12 +126,20 @@ class AjaxableFormView(object): form = self.form_class(*form_args, **form_kwargs) response_data = None - template = self.template if request.is_ajax() else self.full_template + title = self.title + if request.is_ajax(): + template = self.template + else: + template = self.full_template + cd = self.context_description(request, obj) + if cd: + title += ": " + cd if self.placeholdize: form = placeholdized(form) context = { - self.formname: form, - "title": self.title, + self.formname: form, + "title": title, + "honeypot": self.honeypot, "placeholdize": self.placeholdize, "submit": self.submit, "response_data": response_data, @@ -137,21 +147,39 @@ class AjaxableFormView(object): "view_args": args, "view_kwargs": kwargs, } - context.update(self.extra_context()) + context.update(self.extra_context(request, obj)) return render_to_response(template, context, context_instance=RequestContext(request)) - def form_args(self, request, *args, **kwargs): + def redirect_or_refresh(self, request, path, message=None): + """If the form is AJAX, refresh the page. If not, go to `path`.""" + if request.is_ajax(): + output = "" + if message: + output = "
" + message + "
" + output + return HttpResponse(output) + else: + return HttpResponseRedirect(path) + + def get_object(self, request, *args, **kwargs): + """Override to parse view args and get some associated data.""" + return None + + def form_args(self, request, obj): """Override to parse view args and give additional args to the form.""" return (), {} - def extra_context(self): + def extra_context(self, request, obj): """Override to pass something to template.""" return {} + def context_description(self, request, obj): + """Description to appear in standalone form, but not in AJAX form.""" + return "" + def success(self, form, request): """What to do when the form is valid. - + By default, just save the form. """