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/djangobb/djangobb_forum/util.py

300 lines
8.8 KiB
Python
Raw Normal View History

2009-01-05 14:30:08 +02:00
from datetime import datetime
import os.path
import random
2009-01-17 14:42:12 +02:00
import re
2009-01-09 16:11:30 +02:00
from HTMLParser import HTMLParser
try:
import markdown
except ImportError:
pass
2009-01-05 14:30:08 +02:00
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponse, Http404
2009-01-05 14:30:08 +02:00
from django.utils.functional import Promise
2009-03-03 18:30:41 +02:00
from django.utils.translation import force_unicode, check_for_language
2009-01-05 14:30:08 +02:00
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.contrib.sites.models import Site
2009-03-03 18:30:41 +02:00
from django.conf import settings
2009-01-05 14:30:08 +02:00
main app moved from apps/forum to djangobb_forum. Warning: you must renaming DB tables prefix! --HG-- rename : djangobb/apps/forum/__init__.py => djangobb/djangobb_forum/__init__.py rename : djangobb/apps/forum/admin.py => djangobb/djangobb_forum/admin.py rename : djangobb/apps/forum/context_processors.py => djangobb/djangobb_forum/context_processors.py rename : djangobb/apps/forum/feeds.py => djangobb/djangobb_forum/feeds.py rename : djangobb/apps/forum/fields.py => djangobb/djangobb_forum/fields.py rename : djangobb/apps/forum/forms.py => djangobb/djangobb_forum/forms.py rename : djangobb/apps/forum/index.py => djangobb/djangobb_forum/index.py rename : djangobb/apps/forum/locale/ru/LC_MESSAGES/django.mo => djangobb/djangobb_forum/locale/ru/LC_MESSAGES/django.mo rename : djangobb/apps/forum/locale/ru/LC_MESSAGES/django.po => djangobb/djangobb_forum/locale/ru/LC_MESSAGES/django.po rename : djangobb/apps/forum/locale/zh_CN/LC_MESSAGES/django.mo => djangobb/djangobb_forum/locale/zh_CN/LC_MESSAGES/django.mo rename : djangobb/apps/forum/locale/zh_CN/LC_MESSAGES/django.po => djangobb/djangobb_forum/locale/zh_CN/LC_MESSAGES/django.po rename : djangobb/apps/forum/management/__init__.py => djangobb/djangobb_forum/management/__init__.py rename : djangobb/apps/forum/management/commands/__init__.py => djangobb/djangobb_forum/management/commands/__init__.py rename : djangobb/apps/forum/management/commands/unban.py => djangobb/djangobb_forum/management/commands/unban.py rename : djangobb/apps/forum/markups/__init__.py => djangobb/djangobb_forum/markups/__init__.py rename : djangobb/apps/forum/markups/mypostmarkup.py => djangobb/djangobb_forum/markups/mypostmarkup.py rename : djangobb/apps/forum/markups/postmarkup.py => djangobb/djangobb_forum/markups/postmarkup.py rename : djangobb/apps/forum/middleware.py => djangobb/djangobb_forum/middleware.py rename : djangobb/apps/forum/models.py => djangobb/djangobb_forum/models.py rename : djangobb/apps/forum/settings.py => djangobb/djangobb_forum/settings.py rename : djangobb/apps/forum/signals.py => djangobb/djangobb_forum/signals.py rename : djangobb/apps/forum/subscription.py => djangobb/djangobb_forum/subscription.py rename : djangobb/apps/forum/templates/forum/add_post.html => djangobb/djangobb_forum/templates/forum/add_post.html rename : djangobb/apps/forum/templates/forum/base.html => djangobb/djangobb_forum/templates/forum/base.html rename : djangobb/apps/forum/templates/forum/delete_posts.html => djangobb/djangobb_forum/templates/forum/delete_posts.html rename : djangobb/apps/forum/templates/forum/edit_post.html => djangobb/djangobb_forum/templates/forum/edit_post.html rename : djangobb/apps/forum/templates/forum/feeds/posts_description.html => djangobb/djangobb_forum/templates/forum/feeds/posts_description.html rename : djangobb/apps/forum/templates/forum/feeds/posts_title.html => djangobb/djangobb_forum/templates/forum/feeds/posts_title.html rename : djangobb/apps/forum/templates/forum/feeds/topics_description.html => djangobb/djangobb_forum/templates/forum/feeds/topics_description.html rename : djangobb/apps/forum/templates/forum/feeds/topics_title.html => djangobb/djangobb_forum/templates/forum/feeds/topics_title.html rename : djangobb/apps/forum/templates/forum/forum.html => djangobb/djangobb_forum/templates/forum/forum.html rename : djangobb/apps/forum/templates/forum/forum_row.html => djangobb/djangobb_forum/templates/forum/forum_row.html rename : djangobb/apps/forum/templates/forum/header.html => djangobb/djangobb_forum/templates/forum/header.html rename : djangobb/apps/forum/templates/forum/index.html => djangobb/djangobb_forum/templates/forum/index.html rename : djangobb/apps/forum/templates/forum/lofi/base.html => djangobb/djangobb_forum/templates/forum/lofi/base.html rename : djangobb/apps/forum/templates/forum/lofi/footer.html => djangobb/djangobb_forum/templates/forum/lofi/footer.html rename : djangobb/apps/forum/templates/forum/lofi/forum.html => djangobb/djangobb_forum/templates/forum/lofi/forum.html rename : djangobb/apps/forum/templates/forum/lofi/header.html => djangobb/djangobb_forum/templates/forum/lofi/header.html rename : djangobb/apps/forum/templates/forum/lofi/index.html => djangobb/djangobb_forum/templates/forum/lofi/index.html rename : djangobb/apps/forum/templates/forum/lofi/pagination.html => djangobb/djangobb_forum/templates/forum/lofi/pagination.html rename : djangobb/apps/forum/templates/forum/lofi/topic.html => djangobb/djangobb_forum/templates/forum/lofi/topic.html rename : djangobb/apps/forum/templates/forum/mail_to.html => djangobb/djangobb_forum/templates/forum/mail_to.html rename : djangobb/apps/forum/templates/forum/moderate.html => djangobb/djangobb_forum/templates/forum/moderate.html rename : djangobb/apps/forum/templates/forum/moderators.html => djangobb/djangobb_forum/templates/forum/moderators.html rename : djangobb/apps/forum/templates/forum/move_topic.html => djangobb/djangobb_forum/templates/forum/move_topic.html rename : djangobb/apps/forum/templates/forum/pagination.html => djangobb/djangobb_forum/templates/forum/pagination.html rename : djangobb/apps/forum/templates/forum/pm/base_pm.html => djangobb/djangobb_forum/templates/forum/pm/base_pm.html rename : djangobb/apps/forum/templates/forum/pm/create_pm.html => djangobb/djangobb_forum/templates/forum/pm/create_pm.html rename : djangobb/apps/forum/templates/forum/pm/inbox.html => djangobb/djangobb_forum/templates/forum/pm/inbox.html rename : djangobb/apps/forum/templates/forum/pm/menu_pm.html => djangobb/djangobb_forum/templates/forum/pm/menu_pm.html rename : djangobb/apps/forum/templates/forum/pm/message.html => djangobb/djangobb_forum/templates/forum/pm/message.html rename : djangobb/apps/forum/templates/forum/pm/outbox.html => djangobb/djangobb_forum/templates/forum/pm/outbox.html rename : djangobb/apps/forum/templates/forum/post_preview.html => djangobb/djangobb_forum/templates/forum/post_preview.html rename : djangobb/apps/forum/templates/forum/profile/profile_admin.html => djangobb/djangobb_forum/templates/forum/profile/profile_admin.html rename : djangobb/apps/forum/templates/forum/profile/profile_display.html => djangobb/djangobb_forum/templates/forum/profile/profile_display.html rename : djangobb/apps/forum/templates/forum/profile/profile_essentials.html => djangobb/djangobb_forum/templates/forum/profile/profile_essentials.html rename : djangobb/apps/forum/templates/forum/profile/profile_menu.html => djangobb/djangobb_forum/templates/forum/profile/profile_menu.html rename : djangobb/apps/forum/templates/forum/profile/profile_messaging.html => djangobb/djangobb_forum/templates/forum/profile/profile_messaging.html rename : djangobb/apps/forum/templates/forum/profile/profile_personal.html => djangobb/djangobb_forum/templates/forum/profile/profile_personal.html rename : djangobb/apps/forum/templates/forum/profile/profile_personality.html => djangobb/djangobb_forum/templates/forum/profile/profile_personality.html rename : djangobb/apps/forum/templates/forum/profile/profile_privacy.html => djangobb/djangobb_forum/templates/forum/profile/profile_privacy.html rename : djangobb/apps/forum/templates/forum/report.html => djangobb/djangobb_forum/templates/forum/report.html rename : djangobb/apps/forum/templates/forum/reputation.html => djangobb/djangobb_forum/templates/forum/reputation.html rename : djangobb/apps/forum/templates/forum/reputation_form.html => djangobb/djangobb_forum/templates/forum/reputation_form.html rename : djangobb/apps/forum/templates/forum/search_form.html => djangobb/djangobb_forum/templates/forum/search_form.html rename : djangobb/apps/forum/templates/forum/search_posts.html => djangobb/djangobb_forum/templates/forum/search_posts.html rename : djangobb/apps/forum/templates/forum/search_topics.html => djangobb/djangobb_forum/templates/forum/search_topics.html rename : djangobb/apps/forum/templates/forum/topic.html => djangobb/djangobb_forum/templates/forum/topic.html rename : djangobb/apps/forum/templates/forum/upload_avatar.html => djangobb/djangobb_forum/templates/forum/upload_avatar.html rename : djangobb/apps/forum/templates/forum/user.html => djangobb/djangobb_forum/templates/forum/user.html rename : djangobb/apps/forum/templates/forum/users.html => djangobb/djangobb_forum/templates/forum/users.html rename : djangobb/apps/forum/templatetags/__init__.py => djangobb/djangobb_forum/templatetags/__init__.py rename : djangobb/apps/forum/templatetags/forum_extras.py => djangobb/djangobb_forum/templatetags/forum_extras.py rename : djangobb/apps/forum/tests/__init__.py => djangobb/djangobb_forum/tests/__init__.py rename : djangobb/apps/forum/tests/postmarkup.py => djangobb/djangobb_forum/tests/postmarkup.py rename : djangobb/apps/forum/urls.py => djangobb/djangobb_forum/urls.py rename : djangobb/apps/forum/util.py => djangobb/djangobb_forum/util.py rename : djangobb/apps/forum/views.py => djangobb/djangobb_forum/views.py
2009-12-23 17:06:48 +02:00
from djangobb_forum import settings as forum_settings
from djangobb_forum.markups import bbmarkup
2009-03-03 18:30:41 +02:00
2009-01-21 18:28:36 +02:00
#compile smiles regexp
_SMILES = [(re.compile(smile_re), path) for smile_re, path in forum_settings.SMILES]
2009-01-21 01:13:46 +02:00
def render_to(template):
2009-01-05 14:30:08 +02:00
"""
Decorator for Django views that sends returned dict to render_to_response function.
2009-01-05 14:30:08 +02:00
Template name can be decorator parameter or TEMPLATE item in returned dictionary.
RequestContext always added as context instance.
2009-01-21 01:13:46 +02:00
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}
2009-01-21 01:13:46 +02:00
# equals to
def foo(request):
bar = Bar.object.all()
return render_to_response('template.html',
{'bar': bar},
context_instance=RequestContext(request))
2009-01-21 01:13:46 +02:00
# 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))
2009-01-21 01:13:46 +02:00
"""
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))
2009-01-21 01:13:46 +02:00
return wrapper
return renderer
2009-01-05 14:30:08 +02:00
2009-01-19 19:50:01 +02:00
def absolute_url(path):
return 'http://%s%s' % (Site.objects.get_current().domain, path)
2009-01-05 14:30:08 +02:00
def paged(paged_list_name, per_page):
2009-01-05 14:30:08 +02:00
"""
Parse page from GET data and pass it to view. Split the
query set returned from view.
"""
2009-01-05 14:30:08 +02:00
def decorator(func):
def wrapper(request, *args, **kwargs):
result = func(request, *args, **kwargs)
if not isinstance(result, dict) or 'paged_qs' not in result:
2009-01-05 14:30:08 +02:00
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)
2009-08-27 17:41:42 +03:00
try:
result[paged_list_name] = paginator.page(page).object_list
except (InvalidPage, EmptyPage):
raise Http404
2009-01-05 14:30:08 +02:00
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)
2010-01-05 15:56:19 +02:00
2009-01-05 14:30:08 +02:00
def build_form(Form, _request, GET=False, *args, **kwargs):
"""
Shorcut for building the form instance of given form class
2009-01-05 14:30:08 +02:00
"""
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
2010-01-05 15:56:19 +02:00
2009-01-21 18:28:36 +02:00
class ExcludeTagsHTMLParser(HTMLParser):
"""
Class for html parsing with excluding specified tags.
"""
def __init__(self, func, tags=('a', 'code')):
2009-01-09 16:11:30 +02:00
HTMLParser.__init__(self)
2009-01-21 18:28:36 +02:00
self.func = func
self.is_ignored = False
self.tags = tags
self.html = []
2009-01-09 16:11:30 +02:00
def handle_starttag(self, tag, attrs):
2009-01-21 18:28:36 +02:00
self.html.append('<%s%s>' % (tag, self.__html_attrs(attrs)))
if tag in self.tags:
self.is_ignored = True
2009-01-09 16:11:30 +02:00
def handle_data(self, data):
2009-01-21 18:28:36 +02:00
if not self.is_ignored:
data = self.func(data)
self.html.append(data)
2009-01-09 16:11:30 +02:00
def handle_startendtag(self, tag, attrs):
2009-01-21 18:28:36 +02:00
self.html.append('<%s%s/>' % (tag, self.__html_attrs(attrs)))
2009-01-09 16:11:30 +02:00
def handle_endtag(self, tag):
2009-01-21 18:28:36 +02:00
self.is_ignored = False
self.html.append('</%s>' % (tag))
2009-01-20 17:42:02 +02:00
def handle_entityref(self, name):
2009-01-21 18:28:36 +02:00
self.html.append('&%s;' % name)
2009-01-20 17:42:02 +02:00
def handle_charref(self, name):
self.html.append('&#%s;' % name)
2009-01-20 17:42:02 +02:00
2010-01-05 15:56:19 +02:00
def unescape(self, s):
#we don't need unescape data (without this possible XSS-attack)
return s
2009-01-09 16:11:30 +02:00
def __html_attrs(self, attrs):
_attrs = ''
if attrs:
_attrs = ' %s' % (' '.join([('%s="%s"' % (k,v)) for k,v in attrs]))
return _attrs
2009-01-21 18:28:36 +02:00
2009-01-09 16:11:30 +02:00
def feed(self, data):
HTMLParser.feed(self, data)
2009-01-21 18:28:36 +02:00
self.html = ''.join(self.html)
2010-01-05 15:56:19 +02:00
2009-01-21 18:28:36 +02:00
def urlize(data):
"""
Urlize plain text links in the HTML contents.
Do not urlize content of A and CODE tags.
"""
parser = ExcludeTagsHTMLParser(django_urlize)
2009-01-09 16:11:30 +02:00
parser.feed(data)
2009-01-21 18:28:36 +02:00
urlized_html = parser.html
2009-01-09 16:11:30 +02:00
parser.close()
return urlized_html
2009-01-05 14:30:08 +02:00
2009-01-21 18:28:36 +02:00
def _smile_replacer(data):
for smile, path in _SMILES:
data = smile.sub(path, data)
2009-01-17 14:42:12 +02:00
return data
2009-01-21 18:28:36 +02:00
def smiles(data):
"""
Replace text smiles.
"""
parser = ExcludeTagsHTMLParser(_smile_replacer)
parser.feed(data)
smiled_html = parser.html
parser.close()
return smiled_html
2009-02-09 20:31:19 +02:00
def paginate(items, request, per_page, total_count=None):
try:
page_number = int(request.GET.get('page', 1))
except ValueError:
page_number = 1
2009-10-19 14:02:27 +03:00
2009-02-09 20:31:19 +02:00
paginator = Paginator(items, per_page)
pages = paginator.num_pages
try:
paged_list_name = paginator.page(page_number).object_list
except (InvalidPage, EmptyPage):
raise Http404
2009-02-09 20:31:19 +02:00
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)
def convert_text_to_html(text, markup):
if markup == 'bbcode':
text = bbmarkup.bbcode(text)
elif markup == 'markdown':
text = markdown.markdown(text, safe_mode='escape')
else:
raise Exception('Invalid markup property: %s' % markup)
return urlize(text)