source: djangobb/djangobb_forum/util.py @ 223:8630bac391e6

Last change on this file since 223:8630bac391e6 was 223:8630bac391e6, checked in by slav0nic <slav0nic0@…>, 3 years ago

closed #24: Replace postmarkup by django-bbmarkup

File size: 8.3 KB
Line 
1from datetime import datetime
2import os.path
3import random
4import re
5from HTMLParser import HTMLParser
6
7from django.shortcuts import render_to_response
8from django.template import RequestContext
9from django.http import HttpResponse, Http404
10from django.utils.functional import Promise
11from django.utils.translation import force_unicode, check_for_language
12from django.utils.simplejson import JSONEncoder
13from django import forms
14from django.template.defaultfilters import urlize as django_urlize
15from django.core.paginator import Paginator, EmptyPage, InvalidPage
16from django.conf import settings
17
18from djangobb_forum import settings as forum_settings
19
20
21#compile smiles regexp
22_SMILES = [(re.compile(smile_re), path) for smile_re, path in forum_settings.SMILES]
23
24
25def render_to(template):
26    """
27    Decorator for Django views that sends returned dict to render_to_response function.
28
29    Template name can be decorator parameter or TEMPLATE item in returned dictionary.
30    RequestContext always added as context instance.
31    If view doesn't return dict then decorator simply returns output.
32
33    Parameters:
34     - template: template name to use
35
36    Examples:
37    # 1. Template name in decorator parameters
38
39    @render_to('template.html')
40    def foo(request):
41        bar = Bar.object.all() 
42        return {'bar': bar}
43
44    # equals to
45    def foo(request):
46        bar = Bar.object.all() 
47        return render_to_response('template.html',
48                                  {'bar': bar},
49                                  context_instance=RequestContext(request))
50
51    # 2. Template name as TEMPLATE item value in return dictionary
52
53    @render_to()
54    def foo(request, category):
55        template_name = '%s.html' % category
56        return {'bar': bar, 'TEMPLATE': template_name}
57   
58    #equals to
59    def foo(request, category):
60        template_name = '%s.html' % category
61        return render_to_response(template_name,
62                                  {'bar': bar},
63                                  context_instance=RequestContext(request))
64    """
65
66    def renderer(function):
67        def wrapper(request, *args, **kwargs):
68            output = function(request, *args, **kwargs)
69            if not isinstance(output, dict):
70                return output
71            tmpl = output.pop('TEMPLATE', template)
72            return render_to_response(tmpl, output, context_instance=RequestContext(request))
73        return wrapper
74    return renderer
75
76
77def absolute_url(path):
78    return 'http://%s%s' % (forum_settings.HOST, path)
79
80
81def paged(paged_list_name, per_page):
82    """
83    Parse page from GET data and pass it to view. Split the
84    query set returned from view.
85    """
86
87    def decorator(func):
88        def wrapper(request, *args, **kwargs):
89            result = func(request, *args, **kwargs)
90            if not isinstance(result, dict) or 'paged_qs' not in result:
91                return result
92            try:
93                page = int(request.GET.get('page', 1))
94            except ValueError:
95                page = 1
96
97            real_per_page = per_page
98
99            #if per_page_var:
100                #try:
101                    #value = int(request.GET[per_page_var])
102                #except (ValueError, KeyError):
103                    #pass
104                #else:
105                    #if value > 0:
106                        #real_per_page = value
107
108            from django.core.paginator import Paginator
109            paginator = Paginator(result['paged_qs'], real_per_page)
110            try:
111                result[paged_list_name] = paginator.page(page).object_list
112            except (InvalidPage, EmptyPage):
113                raise Http404
114            result['page'] = page
115            result['page_list'] = range(1, paginator.num_pages + 1)
116            result['pages'] = paginator.num_pages
117            result['per_page'] = real_per_page
118            result['request'] = request
119            return result
120        return wrapper
121
122    return decorator
123
124
125def ajax(func):
126    """
127    Checks request.method is POST. Return error in JSON in other case.
128
129    If view returned dict, returns JsonResponse with this dict as content.
130    """
131    def wrapper(request, *args, **kwargs):
132        if request.method == 'POST':
133            try:
134                response = func(request, *args, **kwargs)
135            except Exception, ex:
136                response = {'error': traceback.format_exc()}
137        else:
138            response = {'error': {'type': 403, 'message': 'Accepts only POST request'}}
139        if isinstance(response, dict):
140            return JsonResponse(response)
141        else:
142            return response
143    return wrapper
144
145
146class LazyJSONEncoder(JSONEncoder):
147    """
148    This fing need to save django from crashing.
149    """
150
151    def default(self, o):
152        if isinstance(o, Promise):
153            return force_unicode(o)
154        else:
155            return super(LazyJSONEncoder, self).default(o)
156
157
158class JsonResponse(HttpResponse):
159    """
160    HttpResponse subclass that serialize data into JSON format.
161    """
162
163    def __init__(self, data, mimetype='application/json'):
164        json_data = LazyJSONEncoder().encode(data)
165        super(JsonResponse, self).__init__(
166            content=json_data, mimetype=mimetype)
167
168       
169def build_form(Form, _request, GET=False, *args, **kwargs):
170    """
171    Shorcut for building the form instance of given form class
172    """
173
174    if not GET and 'POST' == _request.method:
175        form = Form(_request.POST, _request.FILES, *args, **kwargs)
176    elif GET and 'GET' == _request.method:
177        form = Form(_request.GET, _request.FILES, *args, **kwargs)
178    else:
179        form = Form(*args, **kwargs)
180    return form
181
182class ExcludeTagsHTMLParser(HTMLParser):
183        """
184        Class for html parsing with excluding specified tags.
185        """
186
187        def __init__(self, func, tags=('a', 'code')):
188            HTMLParser.__init__(self)
189            self.func = func
190            self.is_ignored = False
191            self.tags = tags
192            self.html = []
193
194        def handle_starttag(self, tag, attrs):
195            self.html.append('<%s%s>' % (tag, self.__html_attrs(attrs)))
196            if tag in self.tags:
197                self.is_ignored = True
198
199        def handle_data(self, data):
200            if not self.is_ignored:
201                data = self.func(data)
202            self.html.append(data)
203
204        def handle_startendtag(self, tag, attrs):
205            self.html.append('<%s%s/>' % (tag, self.__html_attrs(attrs))) 
206
207        def handle_endtag(self, tag):
208            self.is_ignored = False
209            self.html.append('</%s>' % (tag))
210
211        def handle_entityref(self, name):
212            self.html.append('&%s;' % name)
213
214        def handle_charref(self, name):
215            self.html.append('&#%s;' % name)
216
217        def __html_attrs(self, attrs):
218            _attrs = ''
219            if attrs:
220                _attrs = ' %s' % (' '.join([('%s="%s"' % (k,v)) for k,v in attrs]))
221            return _attrs
222
223        def feed(self, data):
224            HTMLParser.feed(self, data)
225            self.html = ''.join(self.html)
226
227def urlize(data):
228    """
229    Urlize plain text links in the HTML contents.
230   
231    Do not urlize content of A and CODE tags.
232    """
233
234    parser = ExcludeTagsHTMLParser(django_urlize)
235    parser.feed(data)
236    urlized_html = parser.html
237    parser.close()
238    return urlized_html
239
240def _smile_replacer(data):
241    for smile, path in _SMILES:
242        data = smile.sub(path, data)
243    return data
244
245def smiles(data):
246    """
247    Replace text smiles.
248    """
249
250    parser = ExcludeTagsHTMLParser(_smile_replacer)
251    parser.feed(data)
252    smiled_html = parser.html
253    parser.close()
254    return smiled_html
255
256def paginate(items, request, per_page, total_count=None):
257    try:
258        page_number = int(request.GET.get('page', 1))
259    except ValueError:
260        page_number = 1
261
262    paginator = Paginator(items, per_page)
263    pages = paginator.num_pages
264    try:
265        paged_list_name = paginator.page(page_number).object_list
266    except (InvalidPage, EmptyPage):
267        raise Http404
268    return pages, paginator, paged_list_name
269
270def set_language(request, language):
271    """
272    Change the language of session of authenticated user.
273    """
274
275    if language and check_for_language(language):
276        if hasattr(request, 'session'):
277            request.session['django_language'] = language
278        else:
279            response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language) 
Note: See TracBrowser for help on using the repository browser.