This repository has been archived on 2025-05-04. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
s2forums/apps/forum/util.py
2009-08-27 17:41:42 +03:00

276 lines
8.3 KiB
Python

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('</%s>' % (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)