add poll feature ref #13 as squash commit see also http://support.djangobb.org/topic/333/ (This is a combination of 9 commits.)
This commit is contained in:
parent
725fecaedf
commit
c67ed01f3b
13 changed files with 668 additions and 147 deletions
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
*.py[co]
|
||||
*.egg-info
|
||||
.pydevproject
|
||||
.project
|
||||
.settings
|
||||
*.db
|
||||
*.json
|
||||
*.log
|
||||
*~
|
||||
local_settings.py
|
||||
.env
|
||||
build/
|
||||
dist/
|
|
@ -6,7 +6,7 @@ from django.contrib.auth.models import User
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from djangobb_forum.models import Category, Forum, Topic, Post, Profile, Reputation, \
|
||||
Report, Ban, Attachment
|
||||
Report, Ban, Attachment, Poll, PollChoice
|
||||
|
||||
|
||||
class BaseModelAdmin(admin.ModelAdmin):
|
||||
|
@ -71,9 +71,21 @@ class AttachmentAdmin(BaseModelAdmin):
|
|||
list_filter = ("content_type",)
|
||||
|
||||
|
||||
admin.site.unregister(User)
|
||||
class PollChoiceInline(admin.TabularInline):
|
||||
model = PollChoice
|
||||
extra = 3
|
||||
|
||||
class PollAdmin(admin.ModelAdmin):
|
||||
list_display = ("question", "active",)
|
||||
list_display_links = ("question",)
|
||||
list_editable = ("active",)
|
||||
list_filter = ("active",)
|
||||
inlines = [PollChoiceInline]
|
||||
|
||||
|
||||
admin.site.unregister(User)
|
||||
admin.site.register(User, UserAdmin)
|
||||
|
||||
admin.site.register(Category, CategoryAdmin)
|
||||
admin.site.register(Forum, ForumAdmin)
|
||||
admin.site.register(Topic, TopicAdmin)
|
||||
|
@ -83,4 +95,5 @@ admin.site.register(Reputation, ReputationAdmin)
|
|||
admin.site.register(Report, ReportAdmin)
|
||||
admin.site.register(Ban, BanAdmin)
|
||||
admin.site.register(Attachment, AttachmentAdmin)
|
||||
admin.site.register(Poll, PollAdmin)
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# coding: utf-8
|
||||
|
||||
import os.path
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.expressions import F
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from djangobb_forum.models import Topic, Post, Profile, Reputation, Report, \
|
||||
Attachment
|
||||
Attachment, Poll, PollChoice
|
||||
from djangobb_forum import settings as forum_settings
|
||||
from djangobb_forum.util import convert_text_to_html, set_language
|
||||
|
||||
|
@ -44,6 +46,8 @@ SEARCH_IN_CHOICES = (
|
|||
|
||||
|
||||
class AddPostForm(forms.ModelForm):
|
||||
FORM_NAME = "AddPostForm" # used in view and template submit button
|
||||
|
||||
name = forms.CharField(label=_('Subject'), max_length=255,
|
||||
widget=forms.TextInput(attrs={'size':'115'}))
|
||||
attachment = forms.FileField(label=_('Attachment'), required=False)
|
||||
|
@ -293,20 +297,20 @@ class UserSearchForm(forms.Form):
|
|||
sort_by = self.cleaned_data['sort_by']
|
||||
sort_dir = self.cleaned_data['sort_dir']
|
||||
qs = qs.filter(username__contains=username, forum_profile__post_count__gte=forum_settings.POST_USER_SEARCH)
|
||||
if sort_by=='username':
|
||||
if sort_dir=='ASC':
|
||||
if sort_by == 'username':
|
||||
if sort_dir == 'ASC':
|
||||
return qs.order_by('username')
|
||||
elif sort_dir=='DESC':
|
||||
elif sort_dir == 'DESC':
|
||||
return qs.order_by('-username')
|
||||
elif sort_by=='registered':
|
||||
if sort_dir=='ASC':
|
||||
elif sort_by == 'registered':
|
||||
if sort_dir == 'ASC':
|
||||
return qs.order_by('date_joined')
|
||||
elif sort_dir=='DESC':
|
||||
elif sort_dir == 'DESC':
|
||||
return qs.order_by('-date_joined')
|
||||
elif sort_by=='num_posts':
|
||||
if sort_dir=='ASC':
|
||||
elif sort_by == 'num_posts':
|
||||
if sort_dir == 'ASC':
|
||||
return qs.order_by('forum_profile__post_count')
|
||||
elif sort_dir=='DESC':
|
||||
elif sort_dir == 'DESC':
|
||||
return qs.order_by('-forum_profile__post_count')
|
||||
else:
|
||||
return qs
|
||||
|
@ -401,3 +405,83 @@ class ReportForm(forms.ModelForm):
|
|||
if commit:
|
||||
report.save()
|
||||
return report
|
||||
|
||||
|
||||
class VotePollForm(forms.Form):
|
||||
"""
|
||||
Dynamic form for the poll.
|
||||
"""
|
||||
FORM_NAME = "VotePollForm" # used in view and template submit button
|
||||
|
||||
choice = forms.MultipleChoiceField()
|
||||
def __init__(self, poll, *args, **kwargs):
|
||||
self.poll = poll
|
||||
super(VotePollForm, self).__init__(*args, **kwargs)
|
||||
|
||||
choices = self.poll.choices.all().values_list("id", "choice")
|
||||
if self.poll.choice_count == 1:
|
||||
self.fields["choice"] = forms.ChoiceField(
|
||||
choices=choices, widget=forms.RadioSelect
|
||||
)
|
||||
else:
|
||||
self.fields["choice"] = forms.MultipleChoiceField(
|
||||
choices=choices, widget=forms.CheckboxSelectMultiple
|
||||
)
|
||||
|
||||
def clean_choice(self):
|
||||
ids = self.cleaned_data["choice"]
|
||||
count = len(ids)
|
||||
if count > self.poll.choice_count:
|
||||
raise forms.ValidationError(
|
||||
_(u'You have selected too many choices! (Only %i allowed.)') % self.poll.choice_count
|
||||
)
|
||||
return ids
|
||||
|
||||
|
||||
class PollForm(forms.ModelForm):
|
||||
answers = forms.CharField(min_length=2, widget=forms.Textarea,
|
||||
help_text=_("Write each answer on a new line.")
|
||||
)
|
||||
days = forms.IntegerField(required=False, min_value=1,
|
||||
help_text=_("Number of days for this poll to run. Leave empty for never ending poll.")
|
||||
)
|
||||
class Meta:
|
||||
model = Poll
|
||||
fields = ['question', 'choice_count']
|
||||
|
||||
def create_poll(self):
|
||||
"""
|
||||
return True if one field filled with data -> the user wants to create a poll
|
||||
"""
|
||||
return any(self.data.get(key) for key in ('question', 'answers', 'days'))
|
||||
|
||||
def clean_answers(self):
|
||||
# validate if there is more than whitespaces ;)
|
||||
raw_answers = self.cleaned_data["answers"]
|
||||
answers = [answer.strip() for answer in raw_answers.splitlines() if answer.strip()]
|
||||
if len(answers) == 0:
|
||||
raise forms.ValidationError(_(u"There is no valid answer!"))
|
||||
|
||||
# validate length of all answers
|
||||
is_max_length = max([len(answer) for answer in answers])
|
||||
should_max_length = PollChoice._meta.get_field("choice").max_length
|
||||
if is_max_length > should_max_length:
|
||||
raise forms.ValidationError(_(u"One of this answers are too long!"))
|
||||
|
||||
return answers
|
||||
|
||||
def save(self, post):
|
||||
"""
|
||||
Create poll and all answers in PollChoice model.
|
||||
"""
|
||||
poll = super(PollForm, self).save(commit=False)
|
||||
poll.topic = post.topic
|
||||
days = self.cleaned_data["days"]
|
||||
if days:
|
||||
now = datetime.now()
|
||||
poll.deactivate_date = now + timedelta(days=days)
|
||||
poll.save()
|
||||
answers = self.cleaned_data["answers"]
|
||||
for answer in answers:
|
||||
PollChoice.objects.create(poll=poll, choice=answer)
|
||||
|
||||
|
|
226
djangobb_forum/migrations/0005_auto__add_pollchoice__add_poll.py
Normal file
226
djangobb_forum/migrations/0005_auto__add_pollchoice__add_poll.py
Normal file
|
@ -0,0 +1,226 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding model 'PollChoice'
|
||||
db.create_table('djangobb_forum_pollchoice', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('poll', self.gf('django.db.models.fields.related.ForeignKey')(related_name='choices', to=orm['djangobb_forum.Poll'])),
|
||||
('choice', self.gf('django.db.models.fields.CharField')(max_length=200)),
|
||||
('votes', self.gf('django.db.models.fields.IntegerField')(default=0)),
|
||||
))
|
||||
db.send_create_signal('djangobb_forum', ['PollChoice'])
|
||||
|
||||
# Adding model 'Poll'
|
||||
db.create_table('djangobb_forum_poll', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('topic', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['djangobb_forum.Topic'])),
|
||||
('question', self.gf('django.db.models.fields.CharField')(max_length=200)),
|
||||
('choice_count', self.gf('django.db.models.fields.PositiveSmallIntegerField')(default=1)),
|
||||
('active', self.gf('django.db.models.fields.BooleanField')(default=True)),
|
||||
('deactivate_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal('djangobb_forum', ['Poll'])
|
||||
|
||||
# Adding M2M table for field users on 'Poll'
|
||||
db.create_table('djangobb_forum_poll_users', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('poll', models.ForeignKey(orm['djangobb_forum.poll'], null=False)),
|
||||
('user', models.ForeignKey(orm['auth.user'], null=False))
|
||||
))
|
||||
db.create_unique('djangobb_forum_poll_users', ['poll_id', 'user_id'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'PollChoice'
|
||||
db.delete_table('djangobb_forum_pollchoice')
|
||||
|
||||
# Deleting model 'Poll'
|
||||
db.delete_table('djangobb_forum_poll')
|
||||
|
||||
# Removing M2M table for field users on 'Poll'
|
||||
db.delete_table('djangobb_forum_poll_users')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'djangobb_forum.attachment': {
|
||||
'Meta': {'object_name': 'Attachment'},
|
||||
'content_type': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'hash': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'db_index': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.TextField', [], {}),
|
||||
'path': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': "orm['djangobb_forum.Post']"}),
|
||||
'size': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'djangobb_forum.ban': {
|
||||
'Meta': {'object_name': 'Ban'},
|
||||
'ban_end': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'ban_start': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'reason': ('django.db.models.fields.TextField', [], {}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'ban_users'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||
},
|
||||
'djangobb_forum.category': {
|
||||
'Meta': {'ordering': "['position']", 'object_name': 'Category'},
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'})
|
||||
},
|
||||
'djangobb_forum.forum': {
|
||||
'Meta': {'ordering': "['position']", 'object_name': 'Forum'},
|
||||
'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'forums'", 'to': "orm['djangobb_forum.Category']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_forum_post'", 'null': 'True', 'to': "orm['djangobb_forum.Post']"}),
|
||||
'moderators': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
|
||||
'position': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||
'post_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||
'topic_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
|
||||
},
|
||||
'djangobb_forum.poll': {
|
||||
'Meta': {'object_name': 'Poll'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'choice_count': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}),
|
||||
'deactivate_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'question': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'topic': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djangobb_forum.Topic']"}),
|
||||
'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'djangobb_forum.pollchoice': {
|
||||
'Meta': {'object_name': 'PollChoice'},
|
||||
'choice': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'poll': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'choices'", 'to': "orm['djangobb_forum.Poll']"}),
|
||||
'votes': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'djangobb_forum.post': {
|
||||
'Meta': {'ordering': "['created']", 'object_name': 'Post'},
|
||||
'body': ('django.db.models.fields.TextField', [], {}),
|
||||
'body_html': ('django.db.models.fields.TextField', [], {}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'markup': ('django.db.models.fields.CharField', [], {'default': "'bbcode'", 'max_length': '15'}),
|
||||
'topic': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'posts'", 'to': "orm['djangobb_forum.Topic']"}),
|
||||
'updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'updated_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'posts'", 'to': "orm['auth.User']"}),
|
||||
'user_ip': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'djangobb_forum.posttracking': {
|
||||
'Meta': {'object_name': 'PostTracking'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_read': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'topics': ('djangobb_forum.fields.JSONField', [], {'null': 'True'}),
|
||||
'user': ('djangobb_forum.fields.AutoOneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||
},
|
||||
'djangobb_forum.profile': {
|
||||
'Meta': {'object_name': 'Profile'},
|
||||
'aim': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
|
||||
'auto_subscribe': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'avatar': ('djangobb_forum.fields.ExtendedImageField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}),
|
||||
'icq': ('django.db.models.fields.CharField', [], {'max_length': '12', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'jabber': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
|
||||
'language': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '5'}),
|
||||
'location': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'markup': ('django.db.models.fields.CharField', [], {'default': "'bbcode'", 'max_length': '15'}),
|
||||
'msn': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
|
||||
'post_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||
'privacy_permission': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
|
||||
'show_avatar': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'show_signatures': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'show_smilies': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'signature': ('django.db.models.fields.TextField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'signature_html': ('django.db.models.fields.TextField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'theme': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '80'}),
|
||||
'time_zone': ('django.db.models.fields.FloatField', [], {'default': '3.0'}),
|
||||
'user': ('djangobb_forum.fields.AutoOneToOneField', [], {'related_name': "'forum_profile'", 'unique': 'True', 'to': "orm['auth.User']"}),
|
||||
'yahoo': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'})
|
||||
},
|
||||
'djangobb_forum.report': {
|
||||
'Meta': {'object_name': 'Report'},
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'post': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djangobb_forum.Post']"}),
|
||||
'reason': ('django.db.models.fields.TextField', [], {'default': "''", 'max_length': "'1000'", 'blank': 'True'}),
|
||||
'reported_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reported_by'", 'to': "orm['auth.User']"}),
|
||||
'zapped': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'zapped_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'zapped_by'", 'null': 'True', 'to': "orm['auth.User']"})
|
||||
},
|
||||
'djangobb_forum.reputation': {
|
||||
'Meta': {'unique_together': "(('from_user', 'post'),)", 'object_name': 'Reputation'},
|
||||
'from_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputations_from'", 'to': "orm['auth.User']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post'", 'to': "orm['djangobb_forum.Post']"}),
|
||||
'reason': ('django.db.models.fields.TextField', [], {'max_length': '1000'}),
|
||||
'sign': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputations_to'", 'to': "orm['auth.User']"})
|
||||
},
|
||||
'djangobb_forum.topic': {
|
||||
'Meta': {'ordering': "['-updated']", 'object_name': 'Topic'},
|
||||
'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'forum': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'topics'", 'to': "orm['djangobb_forum.Forum']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_topic_post'", 'null': 'True', 'to': "orm['djangobb_forum.Post']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'post_count': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||
'sticky': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'subscriptions'", 'blank': 'True', 'to': "orm['auth.User']"}),
|
||||
'updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'views': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['djangobb_forum']
|
|
@ -1,13 +1,15 @@
|
|||
from datetime import datetime
|
||||
import os
|
||||
import os.path
|
||||
from hashlib import sha1
|
||||
# coding: utf-8
|
||||
|
||||
from datetime import datetime
|
||||
from hashlib import sha1
|
||||
import os
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.db import models
|
||||
from django.db.models import aggregates
|
||||
from django.db.models.signals import post_save
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from djangobb_forum.fields import AutoOneToOneField, ExtendedImageField, JSONField
|
||||
from djangobb_forum.util import smiles, convert_text_to_html
|
||||
|
@ -410,6 +412,54 @@ class Attachment(models.Model):
|
|||
self.path)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class Poll(models.Model):
|
||||
topic = models.ForeignKey(Topic)
|
||||
question = models.CharField(max_length=200)
|
||||
choice_count = models.PositiveSmallIntegerField(default=1,
|
||||
help_text=_("How many choices are allowed simultaneously."),
|
||||
)
|
||||
active = models.BooleanField(default=True,
|
||||
help_text=_("Can users vote to this poll or just see the result?"),
|
||||
)
|
||||
deactivate_date = models.DateTimeField(null=True, blank=True,
|
||||
help_text=_("Point of time after this poll would be automatic deactivated"),
|
||||
)
|
||||
users = models.ManyToManyField(User, blank=True, null=True,
|
||||
help_text=_("Users who has voted this poll."),
|
||||
)
|
||||
def auto_deactivate(self):
|
||||
if self.active and self.deactivate_date:
|
||||
now = datetime.now()
|
||||
if now > self.deactivate_date:
|
||||
self.active = False
|
||||
self.save()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.question
|
||||
|
||||
|
||||
class PollChoice(models.Model):
|
||||
poll = models.ForeignKey(Poll, related_name="choices")
|
||||
choice = models.CharField(max_length=200)
|
||||
votes = models.IntegerField(default=0, editable=False)
|
||||
|
||||
def percent(self):
|
||||
if not self.votes:
|
||||
return 0.0
|
||||
result = PollChoice.objects.filter(poll=self.poll).aggregate(aggregates.Sum("votes"))
|
||||
votes_sum = result["votes__sum"]
|
||||
return float(self.votes) / votes_sum * 100
|
||||
|
||||
def __unicode__(self):
|
||||
return self.choice
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
from .signals import post_saved, topic_saved
|
||||
|
||||
post_save.connect(post_saved, sender=Post, dispatch_uid='djangobb_post_save')
|
||||
|
|
|
@ -73,4 +73,24 @@ $(document).ready(function() {
|
|||
paste("[b]"+nick+"[/b]\n");
|
||||
});
|
||||
$(".username").attr('title', 'Click to paste nick name in reply form.');
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
var obj = $("textarea#id_body");
|
||||
if (obj.length != 1) {
|
||||
// object not found in page -> do nothing
|
||||
return
|
||||
}
|
||||
var text = obj.val().trim();
|
||||
//log("onbeforeunload text:" + text);
|
||||
if (text.length > 3) {
|
||||
// Firefox will not use the string. IE use it
|
||||
// TODO: Translate string
|
||||
return "Leave page with unsaved content?";
|
||||
}
|
||||
// if nothing returned, browser leave the page without any message
|
||||
};
|
||||
$("form#post").bind("submit", function() {
|
||||
//log("unbind onbeforeunload");
|
||||
window.onbeforeunload = null;
|
||||
});
|
||||
});
|
|
@ -315,3 +315,13 @@ TD DIV.tclcon {MARGIN-LEFT: 2.3em}
|
|||
color: #8A1F11;
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
/* for poll results */
|
||||
/****************************************************************/
|
||||
#poll .bar {
|
||||
height: 4px;
|
||||
background-color: #46586A;
|
||||
}
|
||||
#poll li {
|
||||
height: 2.5em;
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
{% extends 'djangobb_forum/base.html' %}
|
||||
{% load forum_extras %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="linkst">
|
||||
<div class="inbox">
|
||||
{% if forum %}
|
||||
<ul class="start"><li><a href="{% url djangobb:index %}">{% trans "Root" %}</a> </li><li>» {% link forum %}</li></ul>
|
||||
{% else %}
|
||||
<ul><li><a href="{% url djangobb:index %}">{% trans "Root" %}</a> </li><li>» {% link topic.forum %}</li><li>» {{ topic }}</li></ul>
|
||||
{% endif %}
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "djangobb_forum/includes/post_form.html" %}
|
||||
|
||||
{% if not forum %}
|
||||
<div id="postreview" class="blockpost">
|
||||
|
||||
<h2><span>{% trans "Topic review (newest first)" %}</span></h2>
|
||||
{% for post in posts reversed %}
|
||||
<div class="box rowodd">
|
||||
<div class="inbox">
|
||||
<div class="postleft">
|
||||
<dl>
|
||||
<dt><strong><a href="javascript:pasteN('{{ post.user.username }}');">{{ post.user.username }}</a></strong></dt>
|
||||
<dd>{% forum_time post.created %}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="postright">
|
||||
<div class="postmsg">
|
||||
{{ post.body_html|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
<div class="postfootright"><ul><li class="postquote"><a onmouseover="copyQ('{{ post.user.username }}');" href="javascript:pasteQ();">{% trans "Quote" %}</a></li></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
17
djangobb_forum/templates/djangobb_forum/add_topic.html
Normal file
17
djangobb_forum/templates/djangobb_forum/add_topic.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
{% extends 'djangobb_forum/base.html' %}
|
||||
{% load forum_extras %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="linkst">
|
||||
<div class="inbox">
|
||||
{% if forum %}
|
||||
<ul class="start"><li><a href="{% url djangobb:index %}">{% trans "Root" %}</a> </li><li>» {% link forum %}</li></ul>
|
||||
{% else %}
|
||||
<ul><li><a href="{% url djangobb:index %}">{% trans "Root" %}</a> </li><li>» {% link topic.forum %}</li><li>» {{ topic }}</li></ul>
|
||||
{% endif %}
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "djangobb_forum/includes/post_form.html" %}
|
||||
{% endblock %}
|
|
@ -2,8 +2,30 @@
|
|||
<div class="blockform" id="reply">
|
||||
<h2><span>{% if forum %}{% trans "New topic" %}{% else %}{% trans "New reply" %}{% endif %}</span></h2>
|
||||
<div class="box">
|
||||
<form id="post" action="{% if forum %}{% url djangobb:add_topic forum.id %}{% else %}{% url djangobb:add_post topic.id %}{% endif %}" method="post" enctype="multipart/form-data">
|
||||
<form id="post" action="{{ form_url|default_if_none:"." }}" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if create_poll_form %}
|
||||
<script>{# TODO: move to html head! #}
|
||||
$(document).ready(function() {
|
||||
$('.poll .infldset').hide();
|
||||
$(".poll").click(function() {
|
||||
$('.poll .infldset').slideDown();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div class="inform poll">
|
||||
<fieldset>
|
||||
<legend>{% trans "Create a poll" %}</legend>
|
||||
<div class="infldset">
|
||||
<div class="rbox">
|
||||
{{ create_poll_form }}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="inform">
|
||||
<fieldset>
|
||||
<legend>{% trans "Write your message and submit" %}</legend>
|
||||
|
@ -33,7 +55,7 @@
|
|||
</fieldset>
|
||||
</div>
|
||||
{% endif %}
|
||||
<p><input type="submit" value="{% trans "Submit" %}" /><a href="javascript:history.go(-1)">{% trans "Go back" %}</a></p>
|
||||
<p><input type="submit" name="{{ form.FORM_NAME }}" value="{% trans "Submit" %}" /><a href="{{ back_url|default_if_none:"javascript:history.go(-1)" }}">{% trans "Go back" %}</a></p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -18,6 +18,37 @@
|
|||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if poll %}
|
||||
<div id="poll" class="block">
|
||||
<h2><span>{% trans "Poll" %}</span></h2>
|
||||
<div class="box">
|
||||
<div class="inbox"><p><strong>{{ poll.question }}</strong></p>
|
||||
{% if poll_form %}
|
||||
<form action="." method="post">{% csrf_token %}
|
||||
{{ poll_form }}
|
||||
{% if poll.choice_count > 1 %}
|
||||
<p>
|
||||
{% blocktrans with count=poll.choice_count %}({{ count }} answers allows.){% endblocktrans %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<input type="submit" name="{{ poll_form.FORM_NAME }}" value="{% trans "Vote" %}" />
|
||||
</form>
|
||||
{% else %}
|
||||
<ul>
|
||||
{% for choice in poll.choices.all %}
|
||||
<li>
|
||||
<div class="bar" style="width:{{ choice.percent }}%;" title="{{ choice.choice }}"> </div>
|
||||
{{ choice.votes }} vote{{ choice.votes|pluralize }} ({{ choice.percent|floatformat:1 }}%) for: {{ choice.choice }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% for post in posts %}
|
||||
<div id="p{{ post.id }}" class="blockpost roweven firstpost">
|
||||
<a name="post-{{ post.id }}"></a>
|
||||
|
@ -152,10 +183,14 @@
|
|||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% if not topic.closed and user.is_authenticated %}
|
||||
|
||||
{% if reply_form %}
|
||||
{% with form=reply_form %}
|
||||
{% include "djangobb_forum/includes/post_form.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% endblock content%}
|
||||
|
||||
{% block controls %}
|
||||
<div class="conl">
|
||||
|
|
|
@ -2,10 +2,10 @@ from django.conf.urls.defaults import *
|
|||
|
||||
from djangobb_forum import settings as forum_settings
|
||||
from djangobb_forum import views as forum_views
|
||||
from djangobb_forum.feeds import LastPosts, LastTopics, LastPostsOnForum,\
|
||||
from djangobb_forum.feeds import LastPosts, LastTopics, LastPostsOnForum, \
|
||||
LastPostsOnCategory, LastPostsOnTopic
|
||||
from djangobb_forum.forms import EssentialsProfileForm,\
|
||||
PersonalProfileForm, MessagingProfileForm, PersonalityProfileForm,\
|
||||
from djangobb_forum.forms import EssentialsProfileForm, \
|
||||
PersonalProfileForm, MessagingProfileForm, PersonalityProfileForm, \
|
||||
DisplayProfileForm, PrivacyProfileForm, UploadAvatarForm
|
||||
|
||||
|
||||
|
@ -54,16 +54,13 @@ urlpatterns = patterns('',
|
|||
|
||||
# Topic
|
||||
url('^topic/(?P<topic_id>\d+)/$', forum_views.show_topic, name='topic'),
|
||||
url('^(?P<forum_id>\d+)/topic/add/$', forum_views.add_post,
|
||||
{'topic_id': None}, name='add_topic'),
|
||||
url('^(?P<forum_id>\d+)/topic/add/$', forum_views.add_topic, name='add_topic'),
|
||||
url('^topic/(?P<topic_id>\d+)/delete_posts/$', forum_views.delete_posts, name='delete_posts'),
|
||||
url('^topic/move/$', forum_views.move_topic, name='move_topic'),
|
||||
url('^topic/(?P<topic_id>\d+)/stick_unstick/(?P<action>[s|u])/$', forum_views.stick_unstick_topic, name='stick_unstick_topic'),
|
||||
url('^topic/(?P<topic_id>\d+)/open_close/(?P<action>[c|o])/$', forum_views.open_close_topic, name='open_close_topic'),
|
||||
|
||||
# Post
|
||||
url('^topic/(?P<topic_id>\d+)/post/add/$', forum_views.add_post,
|
||||
{'forum_id': None}, name='add_post'),
|
||||
url('^post/(?P<post_id>\d+)/$', forum_views.show_post, name='post'),
|
||||
url('^post/(?P<post_id>\d+)/edit/$', forum_views.edit_post, name='edit_post'),
|
||||
url('^post/(?P<post_id>\d+)/delete/$', forum_views.delete_post, name='delete_post'),
|
||||
|
|
|
@ -1,33 +1,35 @@
|
|||
# coding: utf-8
|
||||
|
||||
import math
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseForbidden
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.cache import cache
|
||||
from django.db.models import Q, F, Sum
|
||||
from django.utils.encoding import smart_str
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import transaction
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.db.models import Q, F
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseForbidden
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from haystack.query import SearchQuerySet, SQ
|
||||
|
||||
from djangobb_forum import settings as forum_settings
|
||||
from djangobb_forum.forms import AddPostForm, EditPostForm, UserSearchForm, \
|
||||
PostSearchForm, ReputationForm, MailToForm, EssentialsProfileForm, \
|
||||
PersonalProfileForm, MessagingProfileForm, PersonalityProfileForm, \
|
||||
DisplayProfileForm, PrivacyProfileForm, ReportForm, UploadAvatarForm
|
||||
from djangobb_forum.models import Category, Forum, Topic, Post, Profile, Reputation, \
|
||||
VotePollForm, ReportForm, VotePollForm, PollForm
|
||||
from djangobb_forum.models import Category, Forum, Topic, Post, Reputation, \
|
||||
Attachment, PostTracking
|
||||
from djangobb_forum.templatetags import forum_extras
|
||||
from djangobb_forum.templatetags.forum_extras import forum_moderated_by
|
||||
from djangobb_forum.util import build_form, paginate, set_language, smiles, convert_text_to_html
|
||||
|
||||
from haystack.query import SearchQuerySet, SQ
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
|
||||
|
||||
|
||||
def index(request, full=True):
|
||||
|
@ -312,6 +314,19 @@ def show_forum(request, forum_id, full=True):
|
|||
|
||||
@transaction.commit_on_success
|
||||
def show_topic(request, topic_id, full=True):
|
||||
"""
|
||||
* Display a topic
|
||||
* save a reply
|
||||
* save a poll vote
|
||||
|
||||
TODO: Add reply in lofi mode
|
||||
"""
|
||||
post_request = request.method == "POST"
|
||||
user_is_authenticated = request.user.is_authenticated()
|
||||
if post_request and not user_is_authenticated:
|
||||
# Info: only user that are logged in should get forms in the page.
|
||||
return HttpResponseForbidden()
|
||||
|
||||
topic = get_object_or_404(Topic.objects.select_related(), pk=topic_id)
|
||||
if not topic.forum.category.has_access(request.user):
|
||||
return HttpResponseForbidden()
|
||||
|
@ -323,82 +338,147 @@ def show_topic(request, topic_id, full=True):
|
|||
topic.update_read(request.user)
|
||||
posts = topic.posts.all().select_related()
|
||||
|
||||
initial = {}
|
||||
if request.user.is_authenticated():
|
||||
initial = {
|
||||
'markup': request.user.forum_profile.markup,
|
||||
'subscribe': request.user.forum_profile.auto_subscribe,
|
||||
}
|
||||
form = AddPostForm(topic=topic, initial=initial)
|
||||
|
||||
moderator = request.user.is_superuser or\
|
||||
request.user in topic.forum.moderators.all()
|
||||
if request.user.is_authenticated() and request.user in topic.subscribers.all():
|
||||
moderator = request.user.is_superuser or request.user in topic.forum.moderators.all()
|
||||
if user_is_authenticated and request.user in topic.subscribers.all():
|
||||
subscribed = True
|
||||
else:
|
||||
subscribed = False
|
||||
|
||||
# reply form
|
||||
reply_form = None
|
||||
form_url = None
|
||||
back_url = None
|
||||
if user_is_authenticated and not topic.closed:
|
||||
form_url = request.path + "#reply" # if form validation failed: browser should scroll down to reply form ;)
|
||||
back_url = request.path
|
||||
ip = request.META.get('REMOTE_ADDR', None)
|
||||
post_form_kwargs = {"topic":topic, "user":request.user, "ip":ip}
|
||||
if post_request and AddPostForm.FORM_NAME in request.POST:
|
||||
reply_form = AddPostForm(request.POST, request.FILES, **post_form_kwargs)
|
||||
if reply_form.is_valid():
|
||||
post = reply_form.save()
|
||||
messages.success(request, _("Your reply saved."))
|
||||
return HttpResponseRedirect(post.get_absolute_url())
|
||||
else:
|
||||
reply_form = AddPostForm(
|
||||
initial={
|
||||
'markup': request.user.forum_profile.markup,
|
||||
'subscribe': request.user.forum_profile.auto_subscribe,
|
||||
},
|
||||
**post_form_kwargs
|
||||
)
|
||||
|
||||
# handle poll, if exists
|
||||
poll_form = None
|
||||
polls = topic.poll_set.all()
|
||||
if not polls:
|
||||
poll = None
|
||||
else:
|
||||
poll = polls[0]
|
||||
if user_is_authenticated: # Only logged in users can vote
|
||||
poll.auto_deactivate()
|
||||
has_voted = request.user in poll.users.all()
|
||||
if not post_request or not VotePollForm.FORM_NAME in request.POST:
|
||||
# It's not a POST request or: The reply form was send and not a poll vote
|
||||
if poll.active and not has_voted:
|
||||
poll_form = VotePollForm(poll)
|
||||
else:
|
||||
if not poll.active:
|
||||
messages.error(request, _("This poll is not active!"))
|
||||
return HttpResponseRedirect(topic.get_absolute_url())
|
||||
elif has_voted:
|
||||
messages.error(request, _("You have already vote to this poll in the past!"))
|
||||
return HttpResponseRedirect(topic.get_absolute_url())
|
||||
|
||||
poll_form = VotePollForm(poll, request.POST)
|
||||
if poll_form.is_valid():
|
||||
ids = poll_form.cleaned_data["choice"]
|
||||
queryset = poll.choices.filter(id__in=ids)
|
||||
queryset.update(votes=F('votes') + 1)
|
||||
poll.users.add(request.user) # save that this user has vote
|
||||
messages.success(request, _("Your votes are saved."))
|
||||
return HttpResponseRedirect(topic.get_absolute_url())
|
||||
|
||||
highlight_word = request.GET.get('hl', '')
|
||||
if full:
|
||||
return render(request, 'djangobb_forum/topic.html', {'categories': Category.objects.all(),
|
||||
'topic': topic,
|
||||
'last_post': last_post,
|
||||
'form': form,
|
||||
'form_url': form_url,
|
||||
'reply_form': reply_form,
|
||||
'back_url': back_url,
|
||||
'moderator': moderator,
|
||||
'subscribed': subscribed,
|
||||
'posts': posts,
|
||||
'highlight_word': highlight_word,
|
||||
'poll': poll,
|
||||
'poll_form': poll_form,
|
||||
})
|
||||
else:
|
||||
return render(request, 'djangobb_forum/lofi/topic.html', {'categories': Category.objects.all(),
|
||||
'topic': topic,
|
||||
'posts': posts,
|
||||
'poll': poll,
|
||||
'poll_form': poll_form,
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
@transaction.commit_on_success
|
||||
def add_post(request, forum_id, topic_id):
|
||||
forum = None
|
||||
topic = None
|
||||
posts = None
|
||||
|
||||
if forum_id:
|
||||
def add_topic(request, forum_id):
|
||||
"""
|
||||
create a new topic, with or without poll
|
||||
"""
|
||||
forum = get_object_or_404(Forum, pk=forum_id)
|
||||
if not forum.category.has_access(request.user):
|
||||
return HttpResponseForbidden()
|
||||
elif topic_id:
|
||||
topic = get_object_or_404(Topic, pk=topic_id)
|
||||
posts = topic.posts.all().select_related()
|
||||
if not topic.forum.category.has_access(request.user):
|
||||
return HttpResponseForbidden()
|
||||
if topic and topic.closed:
|
||||
messages.error(request, _("This topic is closed."))
|
||||
return HttpResponseRedirect(topic.get_absolute_url())
|
||||
|
||||
ip = request.META.get('REMOTE_ADDR', None)
|
||||
form = build_form(AddPostForm, request, topic=topic, forum=forum,
|
||||
user=request.user, ip=ip,
|
||||
post_form_kwargs = {"forum":forum, "user":request.user, "ip":ip, }
|
||||
|
||||
if request.method == 'POST':
|
||||
form = AddPostForm(request.POST, request.FILES, **post_form_kwargs)
|
||||
if form.is_valid():
|
||||
all_valid = True
|
||||
else:
|
||||
all_valid = False
|
||||
|
||||
poll_form = PollForm(request.POST)
|
||||
create_poll = poll_form.create_poll()
|
||||
if not create_poll:
|
||||
# All poll fields are empty: User didn't want to create a poll
|
||||
# Don't run validation and remove all form error messages
|
||||
poll_form = PollForm() # create clean form without form errors
|
||||
elif not poll_form.is_valid():
|
||||
all_valid = False
|
||||
|
||||
if all_valid:
|
||||
post = form.save()
|
||||
if create_poll:
|
||||
poll_form.save(post)
|
||||
messages.success(request, _("Topic with poll saved."))
|
||||
else:
|
||||
messages.success(request, _("Topic saved."))
|
||||
return HttpResponseRedirect(post.get_absolute_url())
|
||||
else:
|
||||
form = AddPostForm(
|
||||
initial={
|
||||
'markup': request.user.forum_profile.markup,
|
||||
'subscribe': request.user.forum_profile.auto_subscribe,
|
||||
})
|
||||
},
|
||||
**post_form_kwargs
|
||||
)
|
||||
if forum_id: # Create a new topic
|
||||
poll_form = PollForm()
|
||||
|
||||
if 'post_id' in request.GET:
|
||||
post_id = request.GET['post_id']
|
||||
post = get_object_or_404(Post, pk=post_id)
|
||||
form.fields['body'].initial = u"[quote=%s]%s[/quote]" % (post.user, post.body)
|
||||
|
||||
if form.is_valid():
|
||||
post = form.save();
|
||||
messages.success(request, _("Topic saved."))
|
||||
return HttpResponseRedirect(post.get_absolute_url())
|
||||
|
||||
return render(request, 'djangobb_forum/add_post.html', {'form': form,
|
||||
'posts': posts,
|
||||
'topic': topic,
|
||||
context = {
|
||||
'forum': forum,
|
||||
})
|
||||
'create_poll_form': poll_form,
|
||||
'form': form,
|
||||
'form_url': request.path,
|
||||
'back_url': forum.get_absolute_url(),
|
||||
}
|
||||
return render(request, 'djangobb_forum/add_topic.html', context)
|
||||
|
||||
|
||||
@transaction.commit_on_success
|
||||
|
|
Reference in a new issue