Limit the choices for the other_characters field.
[matthijs/projects/xerxes.git] / influences / forms.py
1 from django.forms.fields import CharField
2 from django.forms.widgets import Textarea
3 from django.forms.models import ModelMultipleChoiceField
4 from threadedcomments.forms import ThreadedCommentForm
5 from xerxes.tools.forms import ContextModelForm
6 from xerxes.tools.widgets import DropDownMultiple
7 from models import Influence, Character
8
9 #
10 # A few comment form classes, to handle the various cases (staff/no staff,
11 # reply to public/private post)
12
13 # It is probably possible to reduce this mess a bit using metaclasses, but I
14 # didn't get this to work yet.
15
16 class InfluenceCommentForm(ThreadedCommentForm):
17     # Force the textare to 80 columns. This is really a hack, we should
18     # rather create a template tag to do this at the template level.
19     comment = CharField(widget=Textarea(attrs={'cols' : 80}))
20     def __init__(self, *args, **kwargs):
21         super(InfluenceCommentForm, self).__init__(*args, **kwargs)
22
23     class Meta(ThreadedCommentForm.Meta):
24         exclude = ('markup', )
25
26 class AdminInfluenceCommentForm(ThreadedCommentForm):
27     comment = CharField(widget=Textarea(attrs={'cols' : 80}))
28     def __init__(self, *args, **kwargs):
29         super(AdminInfluenceCommentForm, self).__init__(*args, **kwargs)
30
31     class Meta(ThreadedCommentForm.Meta):
32         fields = ThreadedCommentForm.Meta.fields + ('is_public',)
33         exclude = ('markup', )
34
35 class AdminPrivateInfluenceCommentForm(ThreadedCommentForm):
36     comment = CharField(widget=Textarea(attrs={'cols' : 80}))
37     def __init__(self, *args, **kwargs):
38         super(AdminPrivateInfluenceCommentForm, self).__init__(*args, **kwargs)
39         self.instance.is_public = False
40
41     class Meta(ThreadedCommentForm.Meta):
42         exclude = ('markup', )
43
44 def get_influence_comment_form(is_staff, reply_to):
45     """ Gets the form class that a user can use to reply to the given comment.
46     reply_to can be None, in which case the form class for a new comment is
47     returned. """
48     allow_markup = False
49     allow_private = is_staff
50     if reply_to:
51         allow_public = reply_to.is_public
52     else:
53         allow_public = True
54     return _get_influence_comment_form(allow_markup, allow_public, allow_private)
55     
56 def _get_influence_comment_form(allow_markup, allow_public, allow_private):
57     """ Internal wrapper that selects the right form class depending on the
58     given options. Should not be called directly, call
59     get_influence_comment_form instead. """
60     if not allow_markup and allow_public and allow_private:
61         return AdminInfluenceCommentForm
62     elif not allow_markup and not allow_public and allow_private:
63         return AdminPrivateInfluenceCommentForm
64     elif not allow_markup and allow_public and not allow_private:
65         return InfluenceCommentForm
66     else:
67         raise Exception("Unsupported configuration")
68
69 class InfluenceForm(ContextModelForm):
70     # Manually define this field so we can select the DropDownMultiple
71     # widget. However, we leave the queryset empty, which characters can
72     # be selected depends on the logged in user and should be set by
73     # setting the choices property in the view.
74     other_characters = ModelMultipleChoiceField(queryset=Character.objects.none(), widget=DropDownMultiple)
75     class Meta:
76         model = Influence
77         fields = ('initiator', 'summary', 'other_characters', 'other_contacts', 'description')
78
79 class CharacterForm(ContextModelForm):
80     class Meta:
81         model = Character
82         fields = ('name', 'type')
83