Rafał Pitoń 10 лет назад
Родитель
Сommit
8739b06779

+ 12 - 2
docs/developers/forms.rst

@@ -80,9 +80,19 @@ ForumsMultipleChoiceField
 Extends ``ModelMultipleChoiceField``.
 
 
-Instead of ``queryset``, both fields expect ``parent`` argument containing ``Forum`` class instance from which forums should be selected. Leave this argument empty for fields to fallback to root category for all categories and forums.
+Because those fields need to be aware of ACL, you are required to call their ``set_acl`` method from your form's ``__init__``::
 
-In addition, you can pass field ACL dictionary to further limit choices to forums browserable by ACL owner.
+
+    class MoveThreadsForm(forms.Form):
+        new_forum = ForumChoiceField(label=_("Move threads to forum"))
+
+        def __init__(self, *args, **kwargs):
+            self.forum = kwargs.pop('forum')
+            acl = kwargs.pop('acl')
+
+            super(MoveThreadsForm, self).__init__(*args, **kwargs)
+
+            self.fields['new_forum'].set_acl(acl)
 
 
 Template Tags

+ 33 - 67
misago/forums/forms.py

@@ -7,88 +7,68 @@ from mptt.forms import *  # noqa
 from misago.core import forms
 from misago.core.validators import validate_sluggable
 
-from misago.forums.models import Forum, ForumRole
+from misago.forums.models import FORUMS_TREE_ID, Forum, ForumRole
 
 
 """
 Fields
 """
-class ForumListLazyQueryset(object):
-    def __init__(self, parent, acl):
-        self.model = Forum
-        self._cache = None
-        self.parent = parent
-        self.acl = acl
-
-    def get_parent(self):
-        if not self.parent:
-            self.parent = Forum.objects.root_category()
-        return self.parent
-
-    def _all(self):
-        queryset = self.get_parent().get_descendants()
-        if self.acl:
-            allowed_ids = [0]
-            for forum_id, perms in self.acl.get('forums', {}).items():
-                if perms.get('can_see') and perms.get('can_browse'):
-                    allowed_ids.append(forum_id)
-            queryset = queryset.filter(id__in=allowed_ids)
-        return queryset.all()
+class AdminForumFieldMixin(object):
+    def __init__(self, *args, **kwargs):
+        self.base_level = kwargs.pop('base_level', 1)
+        kwargs['level_indicator'] = kwargs.get('level_indicator', '- - ')
 
-    def all(self):
-        if not self._cache:
-            self._cache = self._all()
-        return self._cache
+        kwargs.setdefault('queryset',
+                          Forum.objects.filter(tree_id=FORUMS_TREE_ID))
 
-    def filter(self, *args, **kwargs):
-        return self.all().filter(*args, **kwargs)
+        super(AdminForumFieldMixin, self).__init__(*args, **kwargs)
 
-    def exclude(self, *args, **kwargs):
-        return self.all().exclude(*args, **kwargs)
+    def _get_level_indicator(self, obj):
+        level = getattr(obj, obj._mptt_meta.level_attr) - self.base_level
+        if level > 0:
+            return mark_safe(conditional_escape(self.level_indicator) * level)
+        else:
+            return ''
 
-    def order_by(self, *args, **kwargs):
-        return self.all().order_by(*args, **kwargs)
 
-    def none(self):
-        return Forum.objects.none()
+class AdminForumChoiceField(AdminForumFieldMixin, TreeNodeChoiceField):
+    pass
 
-    def __len__(self):
-        return len(self.all())
+
+class AdminForumMultipleChoiceField(AdminForumFieldMixin,
+                                    TreeNodeMultipleChoiceField):
+    pass
 
 
 class MisagoForumMixin(object):
-    def get_queryset(self, acl=None):
-        queryset = self.parent.get_descendants()
+    def __init__(self, *args, **kwargs):
+        self.parent = None
+        if not 'queryset' in kwargs:
+            kwargs['queryset'] = Forum.objects.order_by('lft')
+
+        super(MisagoForumMixin, self).__init__(*args, **kwargs)
+
+    def set_acl(self, acl=None):
+        queryset = Forum.objects.root_category().get_descendants()
         if acl:
             allowed_ids = [0]
             for forum_id, perms in acl.get('forums', {}).items():
                 if perms.get('can_see') and perms.get('can_browse'):
                     allowed_ids.append(forum_id)
             queryset = queryset.filter(id__in=allowed_ids)
-        return queryset
+        self.queryset = queryset
 
     def _get_level_indicator(self, obj):
-        if self.parent:
-            level = obj.level - self.parent.level - 1
-        else:
-            level = obj.level - 1
+        level = obj.level - 1
         return mark_safe(conditional_escape('- - ') * level)
 
 
 class ForumChoiceField(MisagoForumMixin, TreeNodeChoiceField):
-    def __init__(self, parent=None, acl=None, *args, **kwargs):
-        self.parent = parent
-        if not 'queryset' in kwargs:
-            kwargs['queryset'] = ForumListLazyQueryset(parent, acl)
-        super(ForumChoiceField, self).__init__(*args, **kwargs)
+    pass
 
 
 class ForumsMultipleChoiceField(MisagoForumMixin, TreeNodeMultipleChoiceField):
-    def __init__(self, parent=None, acl=None, *args, **kwargs):
-        self.parent = parent
-        if not 'queryset' in kwargs:
-            kwargs['queryset'] = ForumListLazyQueryset(parent, acl)
-        super(ForumsMultipleChoiceField, self).__init__(*args, **kwargs)
+    pass
 
 
 """
@@ -101,20 +81,6 @@ FORUM_ROLES = (
 )
 
 
-class AdminForumChoiceField(TreeNodeChoiceField):
-    def __init__(self, *args, **kwargs):
-        self.base_level = kwargs.pop('base_level', 1)
-        kwargs['level_indicator'] = kwargs.get('level_indicator', '- - ')
-        super(AdminForumChoiceField, self).__init__(*args, **kwargs)
-
-    def _get_level_indicator(self, obj):
-        level = getattr(obj, obj._mptt_meta.level_attr) - self.base_level
-        if level > 0:
-            return mark_safe(conditional_escape(self.level_indicator) * level)
-        else:
-            return ''
-
-
 class ForumFormBase(forms.ModelForm):
     role = forms.ChoiceField(label=_("Type"), choices=FORUM_ROLES)
     name = forms.CharField(

+ 2 - 2
misago/threads/forms/admin.py

@@ -2,7 +2,7 @@ from django.utils.translation import ugettext_lazy as _
 
 from misago.core import forms
 from misago.core.validators import validate_sluggable
-from misago.forums.forms import ForumsMultipleChoiceField
+from misago.forums.forms import AdminForumMultipleChoiceField
 
 from misago.threads.models import Label
 
@@ -13,7 +13,7 @@ class LabelForm(forms.ModelForm):
     css_class = forms.CharField(
         label=_("CSS class"), required=False,
         help_text=_("Optional CSS clas used to style this label."))
-    forums = ForumsMultipleChoiceField(
+    forums = AdminForumMultipleChoiceField(
         label=_('Forums'), required=False,
         widget=forms.CheckboxSelectMultiple(),
         help_text=_('Select forums this label will be available in.'))

+ 10 - 13
misago/threads/forms/moderation.py

@@ -4,13 +4,20 @@ from misago.core import forms
 from misago.forums.forms import ForumChoiceField
 
 
-class MoveThreadsBaseForm(forms.Form):
+class MoveThreadsForm(forms.Form):
+    new_forum = ForumChoiceField(label=_("Move threads to forum"),
+                                 empty_label=None)
+
     def __init__(self, *args, **kwargs):
         self.forum = kwargs.pop('forum')
-        super(MoveThreadsBaseForm, self).__init__(*args, **kwargs)
+        acl = kwargs.pop('acl')
+
+        super(MoveThreadsForm, self).__init__(*args, **kwargs)
+
+        self.fields['new_forum'].set_acl(acl)
 
     def clean(self):
-        data = super(MoveThreadsBaseForm, self).clean()
+        data = super(MoveThreadsForm, self).clean()
 
         new_forum = data.get('new_forum')
         if new_forum:
@@ -27,13 +34,3 @@ class MoveThreadsBaseForm(forms.Form):
             raise forms.ValidationError(_("You have to select forum."))
         return data
 
-
-def MoveThreadsForm(*args, **kwargs):
-    user = kwargs.pop('user')
-    label = kwargs.pop('label', _("Move threads to forum"))
-    forum_field = ForumChoiceField(label=label, acl=user.acl, empty_label=None)
-
-    FormType = type("FinalMoveThreadsForm", (MoveThreadsBaseForm,), {
-        'new_forum': forum_field,
-    })
-    return FormType(*args, **kwargs)

+ 2 - 2
misago/threads/views/generic/forum/actions.py

@@ -199,11 +199,11 @@ class ForumActions(Actions):
     move_threads_template = 'misago/threads/move.html'
 
     def action_move(self, request, threads):
-        form = MoveThreadsForm(user=request.user, forum=self.forum)
+        form = MoveThreadsForm(acl=request.user.acl, forum=self.forum)
 
         if request.method == "POST" and 'submit' in request.POST:
             form = MoveThreadsForm(
-                request.POST, user=request.user, forum=self.forum)
+                request.POST, acl=request.user.acl, forum=self.forum)
             if form.is_valid():
                 new_forum = form.cleaned_data['new_forum']
                 for thread in threads: