source: djangobb_forum/views.py @ 429:a4c0272533a9

Last change on this file since 429:a4c0272533a9 was 429:a4c0272533a9, checked in by Andi Albrecht <albrecht.andi@…>, 14 months ago

Avoid PostTracking?.DoesNotExist? exception when no Posts exist.

This happens on a fresh install when a users clicks on "Show new posts
since last visit".

File size: 25.7 KB
Line 
1import math
2from datetime import datetime, timedelta
3
4from django.shortcuts import get_object_or_404, render
5from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseForbidden
6from django.contrib.auth.models import User
7from django.contrib.auth.decorators import login_required
8from django.contrib.sites.models import Site
9from django.core.urlresolvers import reverse
10from django.core.cache import cache
11from django.db.models import Q, F, Sum
12from django.utils.encoding import smart_str
13from django.db import transaction
14from django.views.decorators.csrf import csrf_exempt
15
16from djangobb_forum.util import build_form, paginate, set_language
17from djangobb_forum.models import Category, Forum, Topic, Post, Profile, Reputation,\
18    Attachment, PostTracking
19from djangobb_forum.forms import AddPostForm, EditPostForm, UserSearchForm,\
20    PostSearchForm, ReputationForm, MailToForm, EssentialsProfileForm,\
21    PersonalProfileForm, MessagingProfileForm, PersonalityProfileForm,\
22    DisplayProfileForm, PrivacyProfileForm, ReportForm, UploadAvatarForm
23from djangobb_forum.templatetags import forum_extras
24from djangobb_forum import settings as forum_settings
25from djangobb_forum.util import smiles, convert_text_to_html
26from djangobb_forum.templatetags.forum_extras import forum_moderated_by
27
28from haystack.query import SearchQuerySet, SQ
29
30
31def index(request, full=True):
32    users_cached = cache.get('users_online', {})
33    users_online = users_cached and User.objects.filter(id__in = users_cached.keys()) or []
34    guests_cached = cache.get('guests_online', {})
35    guest_count = len(guests_cached)
36    users_count = len(users_online)
37
38    cats = {}
39    forums = {}
40    user_groups = request.user.groups.all()
41    if request.user.is_anonymous():  # in django 1.1 EmptyQuerySet raise exception
42        user_groups = []
43    _forums = Forum.objects.filter(
44            Q(category__groups__in=user_groups) | \
45            Q(category__groups__isnull=True)).select_related('last_post__topic',
46                                                            'last_post__user',
47                                                            'category')
48    for forum in _forums:
49        cat = cats.setdefault(forum.category.id,
50            {'id': forum.category.id, 'cat': forum.category, 'forums': []})
51        cat['forums'].append(forum)
52        forums[forum.id] = forum
53
54    cmpdef = lambda a, b: cmp(a['cat'].position, b['cat'].position)
55    cats = sorted(cats.values(), cmpdef)
56
57    to_return = {'cats': cats,
58                'posts': Post.objects.count(),
59                'topics': Topic.objects.count(),
60                'users': User.objects.count(),
61                'users_online': users_online,
62                'online_count': users_count,
63                'guest_count': guest_count,
64                'last_user': User.objects.latest('date_joined'),
65                }
66    if full:
67        return render(request, 'djangobb_forum/index.html', to_return)
68    else:
69        return render(request, 'djangobb_forum/lofi/index.html', to_return)
70
71
72@transaction.commit_on_success
73def moderate(request, forum_id):
74    forum = get_object_or_404(Forum, pk=forum_id)
75    topics = forum.topics.order_by('-sticky', '-updated').select_related()
76    if request.user.is_superuser or request.user in forum.moderators.all():
77        topic_ids = request.POST.getlist('topic_id')
78        if 'move_topics' in request.POST:
79            return render(request,  'djangobb_forum/move_topic.html', {
80                'categories': Category.objects.all(),
81                'topic_ids': topic_ids,
82                'exclude_forum': forum,
83            })
84        elif 'delete_topics' in request.POST:
85            for topic_id in topic_ids:
86                topic = get_object_or_404(Topic, pk=topic_id)
87                topic.delete()
88            return HttpResponseRedirect(reverse('djangobb:index'))
89        elif 'open_topics' in request.POST:
90            for topic_id in topic_ids:
91                open_close_topic(request, topic_id, 'o')
92            return HttpResponseRedirect(reverse('djangobb:index'))
93        elif 'close_topics' in request.POST:
94            for topic_id in topic_ids:
95                open_close_topic(request, topic_id, 'c')
96            return HttpResponseRedirect(reverse('djangobb:index'))
97
98        return render(request, 'djangobb_forum/moderate.html', {'forum': forum,
99                'topics': topics,
100                #'sticky_topics': forum.topics.filter(sticky=True),
101                'posts': forum.posts.count(),
102                })
103    else:
104        raise Http404
105
106
107def search(request):
108    # TODO: move to form
109    if 'action' in request.GET:
110        action = request.GET['action']
111        #FIXME: show_user for anonymous raise exception,
112        #django bug http://code.djangoproject.com/changeset/14087 :|
113        groups = request.user.groups.all() or [] #removed after django > 1.2.3 release
114        topics = Topic.objects.filter(
115                   Q(forum__category__groups__in=groups) | \
116                   Q(forum__category__groups__isnull=True))
117        if action == 'show_24h':
118            date = datetime.today() - timedelta(1)
119            topics = topics.filter(created__gte=date)
120        elif action == 'show_new':
121            try:
122                last_read = PostTracking.objects.get(user=request.user).last_read
123            except PostTracking.DoesNotExist:
124                last_read = None
125            if last_read:
126                topics = topics.filter(last_post__updated__gte=last_read).all()
127            else:
128                #searching more than forum_settings.SEARCH_PAGE_SIZE in this way - not good idea :]
129                topics = [topic for topic in topics[:forum_settings.SEARCH_PAGE_SIZE] if forum_extras.has_unreads(topic, request.user)]
130        elif action == 'show_unanswered':
131            topics = topics.filter(post_count=1)
132        elif action == 'show_subscriptions':
133            topics = topics.filter(subscribers__id=request.user.id)
134        elif action == 'show_user':
135            user_id = request.GET['user_id']
136            posts = Post.objects.filter(user__id=user_id)
137            topics = [post.topic for post in posts if post.topic in topics]
138        elif action == 'search':
139            keywords = request.GET.get('keywords')
140            author = request.GET.get('author')
141            forum = request.GET.get('forum')
142            search_in = request.GET.get('search_in')
143            sort_by = request.GET.get('sort_by')
144            sort_dir = request.GET.get('sort_dir')
145
146            if not (keywords or author):
147                return HttpResponseRedirect(reverse('djangobb:search'))
148
149            query = SearchQuerySet().models(Post)
150
151            if author:
152                query = query.filter(author__username=author)
153
154            if forum != u'0':
155                query = query.filter(forum__id=forum)
156
157            if keywords:
158                if search_in == 'all':
159                    query = query.filter(SQ(topic=keywords) | SQ(text=keywords))
160                elif search_in == 'message':
161                    query = query.filter(text=keywords)
162                elif search_in == 'topic':
163                    query = query.filter(topic=keywords)
164
165            order = {'0': 'created',
166                     '1': 'author',
167                     '2': 'topic',
168                     '3': 'forum'}.get(sort_by, 'created')
169            if sort_dir == 'DESC':
170                order = '-' + order
171
172            posts = query.order_by(order)
173
174            if 'topics' in request.GET['show_as']:
175                topics = []
176                topics_to_exclude = SQ()
177                for post in posts:
178                    if post.object.topic not in topics:
179                        if post.object.topic.forum.category.has_access(request.user):
180                            topics.append(post.object.topic)
181                        else:
182                            topics_to_exclude |= SQ(topic=post.object.topic)
183
184                if topics_to_exclude:
185                    posts = posts.exclude(topics_to_exclude)
186                return render(request, 'djangobb_forum/search_topics.html', {'results': topics})
187            elif 'posts' in request.GET['show_as']:
188                return render(request, 'djangobb_forum/search_posts.html', {'results': topics})
189        return render(request, 'djangobb_forum/search_topics.html', {'results': topics})
190    else:
191        form = PostSearchForm()
192        return render(request, 'djangobb_forum/search_form.html', {'categories': Category.objects.all(),
193                'form': form,
194                })
195
196
197@login_required
198def misc(request):
199    if 'action' in request.GET:
200        action = request.GET['action']
201        if action =='markread':
202            user = request.user
203            PostTracking.objects.filter(user__id=user.id).update(last_read=datetime.now(), topics=None)
204            return HttpResponseRedirect(reverse('djangobb:index'))
205
206        elif action == 'report':
207            if request.GET.get('post_id', ''):
208                post_id = request.GET['post_id']
209                post = get_object_or_404(Post, id=post_id)
210                form = build_form(ReportForm, request, reported_by=request.user, post=post_id)
211                if request.method == 'POST' and form.is_valid():
212                    form.save()
213                    return HttpResponseRedirect(post.get_absolute_url())
214                return render(request, 'djangobb_forum/report.html', {'form':form})
215
216    elif 'submit' in request.POST and 'mail_to' in request.GET:
217        form = MailToForm(request.POST)
218        if form.is_valid():
219            user = get_object_or_404(User, username=request.GET['mail_to'])
220            subject = form.cleaned_data['subject']
221            body = form.cleaned_data['body'] + '\n %s %s [%s]' % (Site.objects.get_current().domain,
222                                                                  request.user.username,
223                                                                  request.user.email)
224            user.email_user(subject, body, request.user.email)
225            return HttpResponseRedirect(reverse('djangobb:index'))
226
227    elif 'mail_to' in request.GET:
228        mailto = get_object_or_404(User, username=request.GET['mail_to'])
229        form = MailToForm()
230        return (request, 'djangobb_forum/mail_to.html', {'form':form,
231                'mailto': mailto,
232               })
233
234
235def show_forum(request, forum_id, full=True):
236    forum = get_object_or_404(Forum, pk=forum_id)
237    if not forum.category.has_access(request.user):
238        return HttpResponseForbidden()
239    topics = forum.topics.order_by('-sticky', '-updated').select_related()
240    moderator = request.user.is_superuser or\
241        request.user in forum.moderators.all()
242    to_return = {'categories': Category.objects.all(),
243                'forum': forum,
244                'posts': forum.post_count,
245                'topics': topics,
246                'moderator': moderator,
247                }
248    if full:
249        return render(request, 'djangobb_forum/forum.html', to_return)
250    else:
251        return render(request, 'djangobb_forum/lofi/forum.html', to_return)
252
253
254@transaction.commit_on_success
255def show_topic(request, topic_id, full=True):
256    topic = get_object_or_404(Topic.objects.select_related(), pk=topic_id)
257    if not topic.forum.category.has_access(request.user):
258        return HttpResponseForbidden()
259    Topic.objects.filter(pk=topic.id).update(views=F('views') + 1)
260
261    last_post = topic.last_post
262
263    if request.user.is_authenticated():
264        topic.update_read(request.user)
265    posts = topic.posts.all().select_related()
266
267    initial = {}
268    if request.user.is_authenticated():
269        initial = {'markup': request.user.forum_profile.markup}
270    form = AddPostForm(topic=topic, initial=initial)
271
272    moderator = request.user.is_superuser or\
273        request.user in topic.forum.moderators.all()
274    if request.user.is_authenticated() and request.user in topic.subscribers.all():
275        subscribed = True
276    else:
277        subscribed = False
278
279    highlight_word = request.GET.get('hl', '')
280    if full:
281        return render(request, 'djangobb_forum/topic.html', {'categories': Category.objects.all(),
282                'topic': topic,
283                'last_post': last_post,
284                'form': form,
285                'moderator': moderator,
286                'subscribed': subscribed,
287                'posts': posts,
288                'highlight_word': highlight_word,
289                })
290    else:
291        return render(request, 'djangobb_forum/lofi/topic.html', {'categories': Category.objects.all(),
292                'topic': topic,
293                'posts': posts,
294                })
295
296
297@login_required
298@transaction.commit_on_success
299def add_post(request, forum_id, topic_id):
300    forum = None
301    topic = None
302    posts = None
303
304    if forum_id:
305        forum = get_object_or_404(Forum, pk=forum_id)
306        if not forum.category.has_access(request.user):
307            return HttpResponseForbidden()
308    elif topic_id:
309        topic = get_object_or_404(Topic, pk=topic_id)
310        posts = topic.posts.all().select_related()
311        if not topic.forum.category.has_access(request.user):
312            return HttpResponseForbidden()
313    if topic and topic.closed:
314        return HttpResponseRedirect(topic.get_absolute_url())
315
316    ip = request.META.get('REMOTE_ADDR', None)
317    form = build_form(AddPostForm, request, topic=topic, forum=forum,
318                      user=request.user, ip=ip,
319                      initial={'markup': request.user.forum_profile.markup})
320
321    if 'post_id' in request.GET:
322        post_id = request.GET['post_id']
323        post = get_object_or_404(Post, pk=post_id)
324        form.fields['body'].initial = "[quote=%s]%s[/quote]" % (post.user, post.body)
325
326    if form.is_valid():
327        post = form.save();
328        return HttpResponseRedirect(post.get_absolute_url())
329
330    return render(request, 'djangobb_forum/add_post.html', {'form': form,
331            'posts': posts,
332            'topic': topic,
333            'forum': forum,
334            })
335
336
337@transaction.commit_on_success
338def upload_avatar(request, username, template=None, form_class=None):
339    user = get_object_or_404(User, username=username)
340    if request.user.is_authenticated() and user == request.user or request.user.is_superuser:
341        form = build_form(form_class, request, instance=user.forum_profile)
342        if request.method == 'POST' and form.is_valid():
343            form.save()
344            return HttpResponseRedirect(reverse('djangobb:forum_profile', args=[user.username]))
345        return render(request, template, {'form': form,
346                'avatar_width': forum_settings.AVATAR_WIDTH,
347                'avatar_height': forum_settings.AVATAR_HEIGHT,
348               })
349    else:
350        topic_count = Topic.objects.filter(user__id=user.id).count()
351        if user.forum_profile.post_count < forum_settings.POST_USER_SEARCH and not request.user.is_authenticated():
352            return HttpResponseRedirect(reverse('user_signin') + '?next=%s' % request.path)
353        return render(request, template, {'profile': user,
354                'topic_count': topic_count,
355               })
356
357
358@transaction.commit_on_success
359def delete_avatar(request, username, section=None, action=None, template=None, form_class=None):
360    user = get_object_or_404(User, username=username)
361    if request.user.is_authenticated() and user == request.user or request.user.is_superuser:
362        if request.method == 'POST':
363            profile = user.forum_profile
364            profile.avatar = None
365            profile.save()
366        return HttpResponseRedirect(reverse('djangobb:forum_profile', args=[user.username]))
367    else:
368        topic_count = Topic.objects.filter(user__id=user.id).count()
369        if user.forum_profile.post_count < forum_settings.POST_USER_SEARCH and not request.user.is_authenticated():
370            return HttpResponseRedirect(reverse('user_signin') + '?next=%s' % request.path)
371        return render(request, template, {'profile': user,
372                'topic_count': topic_count,
373               })
374
375
376@transaction.commit_on_success
377def user(request, username, section='essentials', action=None, template='djangobb_forum/profile/profile_essentials.html', form_class=EssentialsProfileForm):
378    user = get_object_or_404(User, username=username)
379    if request.user.is_authenticated() and user == request.user or request.user.is_superuser:
380        profile_url = reverse('djangobb:forum_profile_%s' % section, args=[user.username])
381        form = build_form(form_class, request, instance=user.forum_profile, extra_args={'request': request})
382        if request.method == 'POST' and form.is_valid():
383            form.save()
384            return HttpResponseRedirect(profile_url)
385        return render(request, template, {'active_menu': section,
386                'profile': user,
387                'form': form,
388               })
389    else:
390        topic_count = Topic.objects.filter(user__id=user.id).count()
391        if user.forum_profile.post_count < forum_settings.POST_USER_SEARCH and not request.user.is_authenticated():
392            return HttpResponseRedirect(reverse('user_signin') + '?next=%s' % request.path)
393        return render(request, template, {'profile': user,
394                'topic_count': topic_count,
395               })
396
397
398@login_required
399@transaction.commit_on_success
400def reputation(request, username):
401    user = get_object_or_404(User, username=username)
402    form = build_form(ReputationForm, request, from_user=request.user, to_user=user)
403
404    if 'action' in request.GET:
405        if request.user == user:
406            return HttpResponseForbidden(u'You can not change the reputation of yourself')
407
408        if 'post_id' in request.GET:
409            post_id = request.GET['post_id']
410            form.fields['post'].initial = post_id
411            if request.GET['action'] == 'plus':
412                form.fields['sign'].initial = 1
413            elif request.GET['action'] == 'minus':
414                form.fields['sign'].initial = -1
415            return render(request, 'djangobb_forum/reputation_form.html', {'form': form})
416        else:
417            raise Http404
418
419    elif request.method == 'POST':
420        if 'del_reputation' in request.POST and request.user.is_superuser:
421            reputation_list = request.POST.getlist('reputation_id')
422            for reputation_id in reputation_list:
423                    reputation = get_object_or_404(Reputation, pk=reputation_id)
424                    reputation.delete()
425            return HttpResponseRedirect(reverse('djangobb:index'))
426        elif form.is_valid():
427            form.save()
428            post_id = request.POST['post']
429            post = get_object_or_404(Post, id=post_id)
430            return HttpResponseRedirect(post.get_absolute_url())
431        else:
432            return render(request, 'djangobb_forum/reputation_form.html', {'form': form})
433    else:
434        reputations = Reputation.objects.filter(to_user__id=user.id).order_by('-time').select_related()
435        return render(request, 'djangobb_forum/reputation.html', {'reputations': reputations,
436                'profile': user.forum_profile,
437               })
438
439
440def show_post(request, post_id):
441    post = get_object_or_404(Post, pk=post_id)
442    count = post.topic.posts.filter(created__lt=post.created).count() + 1
443    page = math.ceil(count / float(forum_settings.TOPIC_PAGE_SIZE))
444    url = '%s?page=%d#post-%d' % (reverse('djangobb:topic', args=[post.topic.id]), page, post.id)
445    return HttpResponseRedirect(url)
446
447
448@login_required
449@transaction.commit_on_success
450def edit_post(request, post_id):
451    from djangobb_forum.templatetags.forum_extras import forum_editable_by
452
453    post = get_object_or_404(Post, pk=post_id)
454    topic = post.topic
455    if not forum_editable_by(post, request.user):
456        return HttpResponseRedirect(post.get_absolute_url())
457    form = build_form(EditPostForm, request, topic=topic, instance=post)
458    if form.is_valid():
459        post = form.save(commit=False)
460        post.updated_by = request.user
461        post.save()
462        return HttpResponseRedirect(post.get_absolute_url())
463
464    return render(request, 'djangobb_forum/edit_post.html', {'form': form,
465            'post': post,
466            })
467
468
469@login_required
470@transaction.commit_on_success
471def delete_posts(request, topic_id):
472
473    topic = Topic.objects.select_related().get(pk=topic_id)
474
475    if forum_moderated_by(topic, request.user):
476        deleted = False
477        post_list = request.POST.getlist('post')
478        for post_id in post_list:
479            if not deleted:
480                deleted = True
481            delete_post(request, post_id)
482        if deleted:
483            return HttpResponseRedirect(topic.get_absolute_url())
484
485    last_post = topic.posts.latest()
486
487    if request.user.is_authenticated():
488        topic.update_read(request.user)
489
490    posts = topic.posts.all().select_related()
491
492    initial = {}
493    if request.user.is_authenticated():
494        initial = {'markup': request.user.forum_profile.markup}
495    form = AddPostForm(topic=topic, initial=initial)
496
497    moderator = request.user.is_superuser or\
498        request.user in topic.forum.moderators.all()
499    if request.user.is_authenticated() and request.user in topic.subscribers.all():
500        subscribed = True
501    else:
502        subscribed = False
503    return render(request, 'djangobb_forum/delete_posts.html', {
504            'topic': topic,
505            'last_post': last_post,
506            'form': form,
507            'moderator': moderator,
508            'subscribed': subscribed,
509            'posts': posts,
510            })
511
512
513@login_required
514@transaction.commit_on_success
515def move_topic(request):
516    if 'topic_id' in request.GET:
517        #if move only 1 topic
518        topic_ids = [request.GET['topic_id']]
519    else:
520        topic_ids = request.POST.getlist('topic_id')
521    first_topic = topic_ids[0]
522    topic = get_object_or_404(Topic, pk=first_topic)
523    from_forum = topic.forum
524    if 'to_forum' in request.POST:
525        to_forum_id = int(request.POST['to_forum'])
526        to_forum = get_object_or_404(Forum, pk=to_forum_id)
527        for topic_id in topic_ids:
528            topic = get_object_or_404(Topic, pk=topic_id)
529            if topic.forum != to_forum:
530                if forum_moderated_by(topic, request.user):
531                    topic.forum = to_forum
532                    topic.save()
533
534        #TODO: not DRY
535        try:
536            last_post = Post.objects.filter(topic__forum__id=from_forum.id).latest()
537        except Post.DoesNotExist:
538            last_post = None
539        from_forum.last_post = last_post
540        from_forum.topic_count = from_forum.topics.count()
541        from_forum.post_count = from_forum.posts.count()
542        from_forum.save()
543        return HttpResponseRedirect(to_forum.get_absolute_url())
544
545    return render(request, 'djangobb_forum/move_topic.html', {'categories': Category.objects.all(),
546            'topic_ids': topic_ids,
547            'exclude_forum': from_forum,
548            })
549
550
551@login_required
552@transaction.commit_on_success
553def stick_unstick_topic(request, topic_id, action):
554
555    topic = get_object_or_404(Topic, pk=topic_id)
556    if forum_moderated_by(topic, request.user):
557        if action == 's':
558            topic.sticky = True
559        elif action == 'u':
560            topic.sticky = False
561        topic.save()
562    return HttpResponseRedirect(topic.get_absolute_url())
563
564
565@login_required
566@transaction.commit_on_success
567def delete_post(request, post_id):
568    post = get_object_or_404(Post, pk=post_id)
569    last_post = post.topic.last_post
570    topic = post.topic
571    forum = post.topic.forum
572
573    allowed = False
574    if request.user.is_superuser or\
575        request.user in post.topic.forum.moderators.all() or \
576        (post.user == request.user and post == last_post):
577        allowed = True
578
579    if not allowed:
580        return HttpResponseRedirect(post.get_absolute_url())
581
582    post.delete()
583
584    try:
585        Topic.objects.get(pk=topic.id)
586    except Topic.DoesNotExist:
587        #removed latest post in topic
588        return HttpResponseRedirect(forum.get_absolute_url())
589    else:
590        return HttpResponseRedirect(topic.get_absolute_url())
591
592
593@login_required
594@transaction.commit_on_success
595def open_close_topic(request, topic_id, action):
596
597    topic = get_object_or_404(Topic, pk=topic_id)
598    if forum_moderated_by(topic, request.user):
599        if action == 'c':
600            topic.closed = True
601        elif action == 'o':
602            topic.closed = False
603        topic.save()
604    return HttpResponseRedirect(topic.get_absolute_url())
605
606
607def users(request):
608    users = User.objects.filter(forum_profile__post_count__gte=forum_settings.POST_USER_SEARCH).order_by('username')
609    form = UserSearchForm(request.GET)
610    users = form.filter(users)
611    return render(request, 'djangobb_forum/users.html', {'users': users,
612            'form': form,
613            })
614
615
616@login_required
617@transaction.commit_on_success
618def delete_subscription(request, topic_id):
619    topic = get_object_or_404(Topic, pk=topic_id)
620    topic.subscribers.remove(request.user)
621    if 'from_topic' in request.GET:
622        return HttpResponseRedirect(reverse('djangobb:topic', args=[topic.id]))
623    else:
624        return HttpResponseRedirect(reverse('djangobb:forum_profile', args=[request.user.username]))
625
626
627@login_required
628@transaction.commit_on_success
629def add_subscription(request, topic_id):
630    topic = get_object_or_404(Topic, pk=topic_id)
631    topic.subscribers.add(request.user)
632    return HttpResponseRedirect(reverse('djangobb:topic', args=[topic.id]))
633
634
635@login_required
636def show_attachment(request, hash):
637    attachment = get_object_or_404(Attachment, hash=hash)
638    file_data = file(attachment.get_absolute_path(), 'rb').read()
639    response = HttpResponse(file_data, mimetype=attachment.content_type)
640    response['Content-Disposition'] = 'attachment; filename="%s"' % smart_str(attachment.name)
641    return response
642
643
644@login_required
645@csrf_exempt
646def post_preview(request):
647    '''Preview for markitup'''
648    markup = request.user.forum_profile.markup
649    data = request.POST.get('data', '')
650
651    data = convert_text_to_html(data, markup)
652    if forum_settings.SMILES_SUPPORT:
653        data = smiles(data)
654    return render(request, 'djangobb_forum/post_preview.html', {'data': data})
Note: See TracBrowser for help on using the repository browser.