Rafał Pitoń 12 лет назад
Родитель
Сommit
847537f4d3

+ 17 - 17
misago/apps/admin/forums/forms.py

@@ -72,10 +72,10 @@ class NewNodeForm(Form, CleanAttrsMixin):
              )
 
     def finalize_form(self):
-        self.fields['parent'] = TreeNodeChoiceField(label=_("Node Parent"), widget=forms.Select,
-                                                    queryset=Forum.objects.get(special='root').get_descendants(include_self=True), level_indicator=u'- - ')
-        self.fields['perms'] = TreeNodeChoiceField(label=_("Copy Permissions from"), widget=forms.Select,
-                                                   queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
+        self.add_field('parent', TreeNodeChoiceField(label=_("Node Parent"), widget=forms.Select,
+                                                     queryset=Forum.objects.get(special='root').get_descendants(include_self=True), level_indicator=u'- - '))
+        self.add_field('perms', TreeNodeChoiceField(label=_("Copy Permissions from"), widget=forms.Select,
+                                                    queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions")))
 
     def clean(self):
         cleaned_data = super(NewNodeForm, self).clean()
@@ -133,8 +133,8 @@ class CategoryForm(Form, CleanAttrsMixin):
              )
 
     def finalize_form(self):
-        self.fields['perms'] = TreeNodeChoiceField(label=_("Copy Permissions from"), widget=forms.Select,
-                                                   queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
+        self.add_field('perms', TreeNodeChoiceField(label=_("Copy Permissions from"), widget=forms.Select,
+                                                    queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions")))
 
 
 class ForumForm(Form, CleanAttrsMixin):
@@ -196,11 +196,11 @@ class ForumForm(Form, CleanAttrsMixin):
               )
 
     def finalize_form(self):
-        self.fields['perms'] = TreeNodeChoiceField(label=_("Copy Permissions from"), widget=forms.Select,
-                                                   queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
-        self.fields['pruned_archive'] = TreeNodeChoiceField(label=_("Archive pruned threads?"),
-                                                            help_text=_('If you want, you can archive pruned threads in other forum instead of deleting them.'),
-                                                            widget=forms.Select, queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't archive pruned threads"))
+        self.add_field('perms', TreeNodeChoiceField(label=_("Copy Permissions from"), widget=forms.Select,
+                                                    queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions")))
+        self.add_field('pruned_archive', TreeNodeChoiceField(label=_("Archive pruned threads?"),
+                                                             help_text=_('If you want, you can archive pruned threads in other forum instead of deleting them.'),
+                                                             widget=forms.Select, queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't archive pruned threads")))
 
     def clean_pruned_archive(self):
         data = self.cleaned_data['pruned_archive']
@@ -241,8 +241,8 @@ class RedirectForm(Form, CleanAttrsMixin):
               )
 
     def finalize_form(self):
-        self.fields['perms'] = TreeNodeChoiceField(label=_("Copy Permissions from"), widget=forms.Select,
-                                                   queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
+        self.add_field('perms', TreeNodeChoiceField(label=_("Copy Permissions from"), widget=forms.Select,
+                                                    queryset=Forum.objects.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions")))
 
 
 class DeleteForm(Form):
@@ -251,10 +251,10 @@ class DeleteForm(Form):
         super(DeleteForm, self).__init__(*args, **kwargs)
 
     def finalize_form(self):
-        self.fields['contents'] = TreeNodeChoiceField(label=_("Move threads to"),
-                                                      widget=forms.Select, queryset=Forum.objects.get(special='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
-        self.fields['subforums'] = TreeNodeChoiceField(label=_("Move subforums to"), widget=forms.Select,
-                                                       queryset=Forum.objects.get(special='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
+        self.add_field('contents', TreeNodeChoiceField(label=_("Move threads to"),
+                                                       widget=forms.Select, queryset=Forum.objects.get(special='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - '))
+        self.add_field('subforums', TreeNodeChoiceField(label=_("Move subforums to"), widget=forms.Select,
+                                                        queryset=Forum.objects.get(special='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - '))
 
     def clean_contents(self):
         data = self.cleaned_data['contents']

+ 7 - 9
misago/apps/admin/forums/views.py

@@ -145,9 +145,7 @@ class NewNode(FormWidget):
         return reverse('admin_forums_edit', model)
 
     def get_initial_data(self, model):
-        print 'CALL!'
         if not self.request.session.get('forums_admin_preffs'):
-            print 'NO PATTERN!'
             return {}
 
         ref = self.request.META.get('HTTP_REFERER')
@@ -264,14 +262,14 @@ class Edit(FormWidget):
     def get_form_instance(self, form, target, initial, post=False):
         form_inst = super(Edit, self).get_form_instance(form, target, initial, post)
         valid_targets = Forum.objects.get(special='root').get_descendants(include_self=target.type == 'category').exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght))
-        if target.role == 'category':
+        if target.type == 'category':
             label = _("Category Parent")
-        if target.role == 'forum':
+        if target.type == 'forum':
             label = _("Forum Parent")
-        if target.role == 'redirect':
+        if target.type == 'redirect':
             label = _("Redirect Parent")
-        form_inst.fields['parent'] = TreeNodeChoiceField(label=label, widget=forms.Select,
-                                                         queryset=valid_targets, level_indicator=u'- - ')
+        form_inst.add_field('parent', TreeNodeChoiceField(label=label, widget=forms.Select,
+                                                          queryset=valid_targets, level_indicator=u'- - '))
         form_inst.target_forum = target
         return form_inst
 
@@ -363,8 +361,8 @@ class Delete(FormWidget):
         if target.type != 'forum':
             del form_inst.fields['contents']
         valid_targets = Forum.objects.get(special='root').get_descendants().exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght))
-        form_inst.fields['subforums'] = TreeNodeChoiceField(label=_("Move subforums to"), widget=forms.Select,
-                                                            queryset=valid_targets, required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
+        form_inst.add_field('subforums', TreeNodeChoiceField(label=_("Move subforums to"), widget=forms.Select,
+                                                             queryset=valid_targets, required=False, empty_label=_("Remove with forum"), level_indicator=u'- - '))
         return form_inst
 
     def submit_form(self, form, target):

+ 173 - 167
misago/forms/forms.py

@@ -1,167 +1,173 @@
-from recaptcha.client.captcha import submit as recaptcha_submit
-import floppyforms as forms
-from django.utils.translation import ugettext_lazy as _
-from misago.conf import settings
-
-class Form(forms.Form):
-    """
-    Misago-native form abstract extending Django's one with automatic trimming
-    of user input, captacha support and more accessible validation errors
-    """
-    validate_repeats = []
-    repeats_errors = []
-    dont_strip = []
-    error_source = None
-
-    def __init__(self, data=None, file=None, request=None, *args, **kwargs):
-        self.form_finalized = False
-        self.request = request
-
-        # Extract request from first arguments
-        if data != None:
-            super(Form, self).__init__(data, file, *args, **kwargs)
-        else:
-            super(Form, self).__init__(*args, **kwargs)
-
-        # Let forms do mumbo-jumbo with fields removing
-        self.ensure_finalization()
-
-        # Kill captcha fields
-        try:
-            if settings.bots_registration != 'recaptcha' or self.request.session.get('captcha_passed'):
-                del self.fields['recaptcha']
-        except KeyError:
-            pass
-        try:
-            if settings.bots_registration != 'qa' or self.request.session.get('captcha_passed'):
-                del self.fields['captcha_qa']
-            else:
-                # Make sure we have any questions loaded
-                self.fields['captcha_qa'].label = settings.qa_test
-                self.fields['captcha_qa'].help_text = settings.qa_test_help
-        except KeyError:
-            pass
-
-    @property
-    def has_captcha(self):
-        return 'recaptcha' in self.fields or 'captcha_qa' in self.fields
-
-    def ensure_finalization(self):
-        if not self.form_finalized:
-            self.form_finalized = True
-            self.finalize_form()
-
-    def finalize_form(self):
-        pass
-
-    def full_clean(self):
-        """
-        Trim inputs and strip newlines
-        """
-        self.ensure_finalization()
-        self.data = self.data.copy()
-        for key, field in self.fields.iteritems():
-            try:
-                if field.__class__.__name__ in ['ModelChoiceField', 'TreeForeignKey'] and self.data[key]:
-                    self.data[key] = int(self.data[key])
-                elif field.__class__.__name__ == 'ModelMultipleChoiceField':
-                    self.data.setlist(key, [int(x) for x in self.data.getlist(key, [])])
-                elif field.__class__.__name__ not in ['DateField', 'DateTimeField']:
-                    if not key in self.dont_strip:
-                        if field.__class__.__name__ in ['MultipleChoiceField', 'TypedMultipleChoiceField']:
-                            self.data.setlist(key, [x.strip() for x in self.data.getlist(key, [])])
-                        else:
-                            self.data[key] = self.data[key].strip()
-                    if field.__class__.__name__ in ['MultipleChoiceField', 'TypedMultipleChoiceField']:
-                        self.data.setlist(key, [x.replace("\r\n", '') for x in self.data.getlist(key, [])])
-                    elif not field.widget.__class__.__name__ in ['Textarea']:
-                        self.data[key] = self.data[key].replace("\r\n", '')
-            except (KeyError, AttributeError):
-                pass
-        super(Form, self).full_clean()
-
-    def clean(self):
-        """
-        Clean data, do magic checks and stuff
-        """
-        cleaned_data = super(Form, self).clean()
-        self._check_all()
-        return cleaned_data
-
-    def clean_recaptcha(self):
-        """
-        Test reCaptcha, scream if it went wrong
-        """
-        response = recaptcha_submit(
-                                    self.request.POST.get('recaptcha_challenge_field'),
-                                    self.request.POST.get('recaptcha_response_field'),
-                                    settings.recaptcha_private,
-                                    self.request.session.get_ip(self.request)
-                                    ).is_valid
-        if not response:
-            raise forms.ValidationError(_("Entered words are incorrect. Please try again."))
-        self.request.session['captcha_passed'] = True
-        return ''
-
-    def clean_captcha_qa(self):
-        """
-        Test QA Captcha, scream if it went wrong
-        """
-
-        if not unicode(self.cleaned_data['captcha_qa']).lower() in (name.lower() for name in unicode(settings.qa_test_answers).splitlines()):
-            raise forms.ValidationError(_("The answer you entered is incorrect."))
-        self.request.session['captcha_passed'] = True
-        return self.cleaned_data['captcha_qa']
-
-    def _check_all(self):
-        # Check repeated fields
-        self._check_repeats()
-        # Check CSRF, we dont allow un-csrf'd forms in Misago
-        self._check_csrf()
-        # Check if we have any errors from fields, if we do, we will set fancy form-wide error message
-        self._check_fields_errors()
-
-    def _check_repeats(self):
-        for index, repeat in enumerate(self.validate_repeats):
-            # Check empty fields
-            for field in repeat:
-                if not field in self.data:
-                    try:
-                        if len(repeat) == 2:
-                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['fill_both']]
-                        else:
-                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['fill_all']]
-                    except (IndexError, KeyError):
-                        if len(repeat) == 2:
-                            self.errors['_'.join(repeat)] = [_("You have to fill in both fields.")]
-                        else:
-                            self.errors['_'.join(repeat)] = [_("You have to fill in all fields.")]
-                    break
-
-            else:
-                # Check different fields
-                past_field = self.data[repeat[0]]
-                for field in repeat:
-                    if self.data[field] != past_field:
-                        try:
-                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['different']]
-                        except (IndexError, KeyError):
-                            self.errors['_'.join(repeat)] = [_("Entered values differ from each other.")]
-                        break
-                    past_field = self.data[field]
-
-
-    def _check_csrf(self):
-        if not self.request.csrf.request_secure(self.request):
-            raise forms.ValidationError(_("Request authorization is invalid. Please resubmit your form."))
-
-    def _check_fields_errors(self):
-        if self.errors:
-            if self.error_source and self.error_source in self.errors:
-                field_error, self.errors[self.error_source] = self.errors[self.error_source][0], []
-                raise forms.ValidationError(field_error)
-            raise forms.ValidationError(_("Form contains errors."))
-        
-    def empty_errors(self):
-        for i in self.errors:
-            self.errors[i] = []
+from django.forms.forms import BoundField
+from recaptcha.client.captcha import submit as recaptcha_submit
+import floppyforms as forms
+from django.utils.translation import ugettext_lazy as _
+from misago.conf import settings
+
+class Form(forms.Form):
+    """
+    Misago-native form abstract extending Django's one with automatic trimming
+    of user input, captacha support and more accessible validation errors
+    """
+    validate_repeats = []
+    repeats_errors = []
+    dont_strip = []
+    error_source = None
+
+    def __init__(self, data=None, file=None, request=None, *args, **kwargs):
+        self.form_finalized = False
+        self.request = request
+
+        # Extract request from first arguments
+        if data != None:
+            super(Form, self).__init__(data, file, *args, **kwargs)
+        else:
+            super(Form, self).__init__(*args, **kwargs)
+
+        # Let forms do mumbo-jumbo with fields removing
+        self.ensure_finalization()
+
+        # Kill captcha fields
+        try:
+            if settings.bots_registration != 'recaptcha' or self.request.session.get('captcha_passed'):
+                del self.fields['recaptcha']
+        except KeyError:
+            pass
+        try:
+            if settings.bots_registration != 'qa' or self.request.session.get('captcha_passed'):
+                del self.fields['captcha_qa']
+            else:
+                # Make sure we have any questions loaded
+                self.fields['captcha_qa'].label = settings.qa_test
+                self.fields['captcha_qa'].help_text = settings.qa_test_help
+        except KeyError:
+            pass
+
+    @property
+    def has_captcha(self):
+        return 'recaptcha' in self.fields or 'captcha_qa' in self.fields
+
+    def ensure_finalization(self):
+        if not self.form_finalized:
+            self.form_finalized = True
+            self.finalize_form()
+
+    def add_field(self, name, field):
+        bound = BoundField(self, field, name)
+        self.__dict__[name] = bound
+        self.fields[name] = field
+
+    def finalize_form(self):
+        pass
+
+    def full_clean(self):
+        """
+        Trim inputs and strip newlines
+        """
+        self.ensure_finalization()
+        self.data = self.data.copy()
+        for key, field in self.fields.iteritems():
+            try:
+                if field.__class__.__name__ in ['ModelChoiceField', 'TreeForeignKey'] and self.data[key]:
+                    self.data[key] = int(self.data[key])
+                elif field.__class__.__name__ == 'ModelMultipleChoiceField':
+                    self.data.setlist(key, [int(x) for x in self.data.getlist(key, [])])
+                elif field.__class__.__name__ not in ['DateField', 'DateTimeField']:
+                    if not key in self.dont_strip:
+                        if field.__class__.__name__ in ['MultipleChoiceField', 'TypedMultipleChoiceField']:
+                            self.data.setlist(key, [x.strip() for x in self.data.getlist(key, [])])
+                        else:
+                            self.data[key] = self.data[key].strip()
+                    if field.__class__.__name__ in ['MultipleChoiceField', 'TypedMultipleChoiceField']:
+                        self.data.setlist(key, [x.replace("\r\n", '') for x in self.data.getlist(key, [])])
+                    elif not field.widget.__class__.__name__ in ['Textarea']:
+                        self.data[key] = self.data[key].replace("\r\n", '')
+            except (KeyError, AttributeError):
+                pass
+        super(Form, self).full_clean()
+
+    def clean(self):
+        """
+        Clean data, do magic checks and stuff
+        """
+        cleaned_data = super(Form, self).clean()
+        self._check_all()
+        return cleaned_data
+
+    def clean_recaptcha(self):
+        """
+        Test reCaptcha, scream if it went wrong
+        """
+        response = recaptcha_submit(
+                                    self.request.POST.get('recaptcha_challenge_field'),
+                                    self.request.POST.get('recaptcha_response_field'),
+                                    settings.recaptcha_private,
+                                    self.request.session.get_ip(self.request)
+                                    ).is_valid
+        if not response:
+            raise forms.ValidationError(_("Entered words are incorrect. Please try again."))
+        self.request.session['captcha_passed'] = True
+        return ''
+
+    def clean_captcha_qa(self):
+        """
+        Test QA Captcha, scream if it went wrong
+        """
+
+        if not unicode(self.cleaned_data['captcha_qa']).lower() in (name.lower() for name in unicode(settings.qa_test_answers).splitlines()):
+            raise forms.ValidationError(_("The answer you entered is incorrect."))
+        self.request.session['captcha_passed'] = True
+        return self.cleaned_data['captcha_qa']
+
+    def _check_all(self):
+        # Check repeated fields
+        self._check_repeats()
+        # Check CSRF, we dont allow un-csrf'd forms in Misago
+        self._check_csrf()
+        # Check if we have any errors from fields, if we do, we will set fancy form-wide error message
+        self._check_fields_errors()
+
+    def _check_repeats(self):
+        for index, repeat in enumerate(self.validate_repeats):
+            # Check empty fields
+            for field in repeat:
+                if not field in self.data:
+                    try:
+                        if len(repeat) == 2:
+                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['fill_both']]
+                        else:
+                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['fill_all']]
+                    except (IndexError, KeyError):
+                        if len(repeat) == 2:
+                            self.errors['_'.join(repeat)] = [_("You have to fill in both fields.")]
+                        else:
+                            self.errors['_'.join(repeat)] = [_("You have to fill in all fields.")]
+                    break
+
+            else:
+                # Check different fields
+                past_field = self.data[repeat[0]]
+                for field in repeat:
+                    if self.data[field] != past_field:
+                        try:
+                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['different']]
+                        except (IndexError, KeyError):
+                            self.errors['_'.join(repeat)] = [_("Entered values differ from each other.")]
+                        break
+                    past_field = self.data[field]
+
+
+    def _check_csrf(self):
+        if not self.request.csrf.request_secure(self.request):
+            raise forms.ValidationError(_("Request authorization is invalid. Please resubmit your form."))
+
+    def _check_fields_errors(self):
+        if self.errors:
+            if self.error_source and self.error_source in self.errors:
+                field_error, self.errors[self.error_source] = self.errors[self.error_source][0], []
+                raise forms.ValidationError(field_error)
+            raise forms.ValidationError(_("Form contains errors."))
+        
+    def empty_errors(self):
+        for i in self.errors:
+            self.errors[i] = []

+ 1 - 1
misago/settings_base.py

@@ -182,7 +182,7 @@ INSTALLED_APPS = (
     'django.contrib.staticfiles',
     'django.contrib.humanize',
     'django_jinja', # Jinja2 integration
-    'django_jinja.contrib.humanize', # Some Django filters    
+    'django_jinja.contrib.humanize', # Some Django filters
     'floppyforms', # Better forms
     'mptt', # Modified Pre-order Tree Transversal - allows us to nest forums 
     'haystack', # Search engines bridge

+ 6 - 0
templates/admin/forums/delete.html

@@ -1,4 +1,10 @@
 {% extends "admin/admin/form.html" %}
+{% import "forms.html" as form_theme with context %}
+
+{% block form %}
+{{ form_theme.row(form.contents, attrs={'class': 'span12'}) }}
+{{ form_theme.row(form.subforums, attrs={'class': 'span12'}) }}
+{% endblock %}
 
 {% block form_submit %}
 <button name="save" type="submit" class="btn btn-danger">{% trans %}Delete Forum{% endtrans %}</button>

+ 21 - 4
templates/admin/forums/form.html

@@ -4,17 +4,34 @@
 {% block form %}
 <fieldset>
   <legend>{% trans %}Basic Options{% endtrans %}</legend>
+	{{ form_theme.row(form.parent, attrs={'class': 'span12'}) }}
+	{{ form_theme.row(form.perms, attrs={'class': 'span12'}) }}
+	{% if 'role' in form.fields %}
+  {{ form_theme.row(form.role, attrs={'class': 'span12'}) }}
+  {% endif %}
+  {{ form_theme.row(form.name, attrs={'class': 'span12'}) }}
+  {{ form_theme.row(form.description, attrs={'class': 'span12', 'rows': 3}) }}
+  {% if 'redirect' in form.fields %}
+  {{ form_theme.row(form.redirect, attrs={'class': 'span12'}) }}
+  {% endif %}
+  {% if 'closed' in form.fields %}
+  {{ form_theme.row(form.closed) }}
+  {% endif %}
 </fieldset>
 {% if 'prune_start' in form.fields %}
 <fieldset>
   <legend>{% trans %}Prune Forums{% endtrans %}</legend>
+  {{ form_theme.row(form.prune_start, attrs={'class': 'span12'}) }}
+  {{ form_theme.row(form.prune_last, attrs={'class': 'span12'}) }}
+  {{ form_theme.row(form.pruned_archive, attrs={'class': 'span12'}) }}
 </fieldset>
 {% endif %}
 <fieldset>
   <legend>{% trans %}Display Options{% endtrans %}</legend>
+  {% if 'attrs' in form.fields %}
+  {{ form_theme.row(form.attrs, attrs={'class': 'span12'}) }}
+  {{ form_theme.row(form.show_details) }}
+  {% endif %}
+  {{ form_theme.row(form.style, attrs={'class': 'span12'}) }}
 </fieldset>
-{{ form_theme.row(form.name, attrs={'class': 'span12'}) }}
-{% if 'protected' in form.fields %}
-{{ form_theme.row(form.protected) }}
-{% endif %}
 {% endblock %}