from datetime import datetime import os.path import random import re from HTMLParser import HTMLParser from django.shortcuts import render_to_response from django.template import RequestContext from django.http import HttpResponse, Http404 from django.utils.functional import Promise from django.utils.translation import force_unicode, check_for_language from django.utils.simplejson import JSONEncoder from django import forms from django.template.defaultfilters import urlize as django_urlize from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.conf import settings from forum import settings as forum_settings #compile smiles regexp _SMILES = [(re.compile(smile_re), path) for smile_re, path in forum_settings.SMILES] def render_to(template): """ Decorator for Django views that sends returned dict to render_to_response function. Template name can be decorator parameter or TEMPLATE item in returned dictionary. RequestContext always added as context instance. If view doesn't return dict then decorator simply returns output. Parameters: - template: template name to use Examples: # 1. Template name in decorator parameters @render_to('template.html') def foo(request): bar = Bar.object.all() return {'bar': bar} # equals to def foo(request): bar = Bar.object.all() return render_to_response('template.html', {'bar': bar}, context_instance=RequestContext(request)) # 2. Template name as TEMPLATE item value in return dictionary @render_to() def foo(request, category): template_name = '%s.html' % category return {'bar': bar, 'TEMPLATE': template_name} #equals to def foo(request, category): template_name = '%s.html' % category return render_to_response(template_name, {'bar': bar}, context_instance=RequestContext(request)) """ def renderer(function): def wrapper(request, *args, **kwargs): output = function(request, *args, **kwargs) if not isinstance(output, dict): return output tmpl = output.pop('TEMPLATE', template) return render_to_response(tmpl, output, context_instance=RequestContext(request)) return wrapper return renderer def absolute_url(path): return 'http://%s%s' % (forum_settings.HOST, path) def paged(paged_list_name, per_page): """ Parse page from GET data and pass it to view. Split the query set returned from view. """ def decorator(func): def wrapper(request, *args, **kwargs): result = func(request, *args, **kwargs) if not isinstance(result, dict) or 'paged_qs' not in result: return result try: page = int(request.GET.get('page', 1)) except ValueError: page = 1 real_per_page = per_page #if per_page_var: #try: #value = int(request.GET[per_page_var]) #except (ValueError, KeyError): #pass #else: #if value > 0: #real_per_page = value from django.core.paginator import Paginator paginator = Paginator(result['paged_qs'], real_per_page) try: result[paged_list_name] = paginator.page(page).object_list except (InvalidPage, EmptyPage): raise Http404 result['page'] = page result['page_list'] = range(1, paginator.num_pages + 1) result['pages'] = paginator.num_pages result['per_page'] = real_per_page result['request'] = request return result return wrapper return decorator def ajax(func): """ Checks request.method is POST. Return error in JSON in other case. If view returned dict, returns JsonResponse with this dict as content. """ def wrapper(request, *args, **kwargs): if request.method == 'POST': try: response = func(request, *args, **kwargs) except Exception, ex: response = {'error': traceback.format_exc()} else: response = {'error': {'type': 403, 'message': 'Accepts only POST request'}} if isinstance(response, dict): return JsonResponse(response) else: return response return wrapper class LazyJSONEncoder(JSONEncoder): """ This fing need to save django from crashing. """ def default(self, o): if isinstance(o, Promise): return force_unicode(o) else: return super(LazyJSONEncoder, self).default(o) class JsonResponse(HttpResponse): """ HttpResponse subclass that serialize data into JSON format. """ def __init__(self, data, mimetype='application/json'): json_data = LazyJSONEncoder().encode(data) super(JsonResponse, self).__init__( content=json_data, mimetype=mimetype) def build_form(Form, _request, GET=False, *args, **kwargs): """ Shorcut for building the form instance of given form class """ if not GET and 'POST' == _request.method: form = Form(_request.POST, _request.FILES, *args, **kwargs) elif GET and 'GET' == _request.method: form = Form(_request.GET, _request.FILES, *args, **kwargs) else: form = Form(*args, **kwargs) return form class ExcludeTagsHTMLParser(HTMLParser): """ Class for html parsing with excluding specified tags. """ def __init__(self, func, tags=('a', 'code')): HTMLParser.__init__(self) self.func = func self.is_ignored = False self.tags = tags self.html = [] def handle_starttag(self, tag, attrs): self.html.append('<%s%s>' % (tag, self.__html_attrs(attrs))) if tag in self.tags: self.is_ignored = True def handle_data(self, data): if not self.is_ignored: data = self.func(data) self.html.append(data) def handle_startendtag(self, tag, attrs): self.html.append('<%s%s/>' % (tag, self.__html_attrs(attrs))) def handle_endtag(self, tag): self.is_ignored = False self.html.append('' % (tag)) def handle_entityref(self, name): self.html.append('&%s;' % name) def handle_charref(self, name): self.html.append('&%s;' % name) def __html_attrs(self, attrs): _attrs = '' if attrs: _attrs = ' %s' % (' '.join([('%s="%s"' % (k,v)) for k,v in attrs])) return _attrs def feed(self, data): HTMLParser.feed(self, data) self.html = ''.join(self.html) def urlize(data): """ Urlize plain text links in the HTML contents. Do not urlize content of A and CODE tags. """ parser = ExcludeTagsHTMLParser(django_urlize) parser.feed(data) urlized_html = parser.html parser.close() return urlized_html def _smile_replacer(data): for smile, path in _SMILES: data = smile.sub(path, data) return data def smiles(data): """ Replace text smiles. """ parser = ExcludeTagsHTMLParser(_smile_replacer) parser.feed(data) smiled_html = parser.html parser.close() return smiled_html def paginate(items, request, per_page, total_count=None): try: page_number = int(request.GET.get('page', 1)) except ValueError: page_number = 1 paginator = Paginator(items, per_page) pages = paginator.num_pages try: paged_list_name = paginator.page(page_number).object_list except (InvalidPage, EmptyPage): raise Http404 return pages, paginator, paged_list_name def set_language(request, language): """ Change the language of session of authenticated user. """ if language and check_for_language(language): if hasattr(request, 'session'): request.session['django_language'] = language else: response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language)