Rename EmailsField to AutocompletedEmailsField and add a singular

AutocompletedEmailField that cleans to a single Email to make it
easier to use with ModelForms
 - Legacy-Id: 8280
This commit is contained in:
Ole Laursen 2014-08-18 11:50:04 +00:00
parent 5703dc3bc6
commit 7b36280070
6 changed files with 28 additions and 20 deletions

View file

@ -29,7 +29,7 @@ from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_p
from ietf.ietfauth.utils import role_required from ietf.ietfauth.utils import role_required
from ietf.message.models import Message from ietf.message.models import Message
from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName
from ietf.person.fields import EmailsField from ietf.person.fields import AutocompletedEmailField
from ietf.person.models import Person, Email from ietf.person.models import Person, Email
from ietf.secr.lib.template import jsonapi from ietf.secr.lib.template import jsonapi
from ietf.utils.mail import send_mail, send_mail_message from ietf.utils.mail import send_mail, send_mail_message
@ -1043,7 +1043,7 @@ def edit_shepherd_writeup(request, name):
context_instance=RequestContext(request)) context_instance=RequestContext(request))
class ShepherdForm(forms.Form): class ShepherdForm(forms.Form):
shepherd = EmailsField(label="Shepherd", required=False, max_entries=1) shepherd = AutocompletedEmailField(required=False)
def edit_shepherd(request, name): def edit_shepherd(request, name):
"""Change the shepherd for a Document""" """Change the shepherd for a Document"""
@ -1060,7 +1060,7 @@ def edit_shepherd(request, name):
if form.is_valid(): if form.is_valid():
save_document_in_history(doc) save_document_in_history(doc)
doc.shepherd = form.cleaned_data['shepherd'].first() doc.shepherd = form.cleaned_data['shepherd']
doc.save() doc.save()
login = request.user.person login = request.user.person

View file

@ -19,7 +19,7 @@ from ietf.group.models import ( Group, Role, GroupEvent, GroupHistory, GroupStat
from ietf.group.utils import save_group_in_history, can_manage_group_type from ietf.group.utils import save_group_in_history, can_manage_group_type
from ietf.group.utils import get_group_or_404 from ietf.group.utils import get_group_or_404
from ietf.ietfauth.utils import has_role from ietf.ietfauth.utils import has_role
from ietf.person.fields import EmailsField from ietf.person.fields import AutocompletedEmailsField
from ietf.person.models import Person, Email from ietf.person.models import Person, Email
from ietf.group.mails import email_iesg_secretary_re_charter from ietf.group.mails import email_iesg_secretary_re_charter
@ -29,10 +29,10 @@ class GroupForm(forms.Form):
name = forms.CharField(max_length=255, label="Name", required=True) name = forms.CharField(max_length=255, label="Name", required=True)
acronym = forms.CharField(max_length=10, label="Acronym", required=True) acronym = forms.CharField(max_length=10, label="Acronym", required=True)
state = forms.ModelChoiceField(GroupStateName.objects.all(), label="State", required=True) state = forms.ModelChoiceField(GroupStateName.objects.all(), label="State", required=True)
chairs = EmailsField(label="Chairs", required=False) chairs = AutocompletedEmailsField(label="Chairs", required=False)
secretaries = EmailsField(label="Secretaries", required=False) secretaries = AutocompletedEmailsField(label="Secretaries", required=False)
techadv = EmailsField(label="Technical Advisors", required=False) techadv = AutocompletedEmailsField(label="Technical Advisors", required=False)
delegates = EmailsField(label="Delegates", required=False, help_text=mark_safe("Chairs can delegate the authority to update the state of group documents - max %s persons at a given time" % MAX_GROUP_DELEGATES), max_entries=MAX_GROUP_DELEGATES) delegates = AutocompletedEmailsField(label="Delegates", required=False, help_text=mark_safe("Chairs can delegate the authority to update the state of group documents - max %s persons at a given time" % MAX_GROUP_DELEGATES), max_entries=MAX_GROUP_DELEGATES)
ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), label="Shepherding AD", empty_label="(None)", required=False) ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), label="Shepherding AD", empty_label="(None)", required=False)
parent = forms.ModelChoiceField(Group.objects.filter(state="active").order_by('name'), empty_label="(None)", required=False) parent = forms.ModelChoiceField(Group.objects.filter(state="active").order_by('name'), empty_label="(None)", required=False)
list_email = forms.CharField(max_length=64, required=False) list_email = forms.CharField(max_length=64, required=False)

View file

@ -10,7 +10,7 @@ from ietf.group.models import Group, GroupEvent, Role
from ietf.group.utils import save_group_in_history from ietf.group.utils import save_group_in_history
from ietf.ietfauth.utils import has_role from ietf.ietfauth.utils import has_role
from ietf.name.models import StreamName from ietf.name.models import StreamName
from ietf.person.fields import EmailsField from ietf.person.fields import AutocompletedEmailsField
from ietf.person.models import Email from ietf.person.models import Email
import debug # pyflakes:ignore import debug # pyflakes:ignore
@ -31,7 +31,7 @@ def stream_documents(request, acronym):
return render_to_response('group/stream_documents.html', {'stream':stream, 'docs':docs, 'meta':meta }, context_instance=RequestContext(request)) return render_to_response('group/stream_documents.html', {'stream':stream, 'docs':docs, 'meta':meta }, context_instance=RequestContext(request))
class StreamEditForm(forms.Form): class StreamEditForm(forms.Form):
delegates = EmailsField(label="Delegates", required=False) delegates = AutocompletedEmailsField(label="Delegates", required=False)
def stream_edit(request, acronym): def stream_edit(request, acronym):
group = get_object_or_404(Group, acronym=acronym) group = get_object_or_404(Group, acronym=acronym)

View file

@ -13,7 +13,7 @@ def json_emails(emails):
emails = Email.objects.filter(address__in=[x.strip() for x in emails.split(",") if x.strip()]).select_related("person") emails = Email.objects.filter(address__in=[x.strip() for x in emails.split(",") if x.strip()]).select_related("person")
return json.dumps([{"id": e.address + "", "name": escape(u"%s <%s>" % (e.person.name, e.address))} for e in emails]) return json.dumps([{"id": e.address + "", "name": escape(u"%s <%s>" % (e.person.name, e.address))} for e in emails])
class EmailsField(forms.CharField): class AutocompletedEmailsField(forms.CharField):
"""Multi-select field using jquery.tokeninput.js. Since the API of """Multi-select field using jquery.tokeninput.js. Since the API of
tokeninput" is asymmetric, we have to pass it a JSON tokeninput" is asymmetric, we have to pass it a JSON
representation on the way out and parse the ids coming back as a representation on the way out and parse the ids coming back as a
@ -25,7 +25,7 @@ class EmailsField(forms.CharField):
self.max_entries = max_entries self.max_entries = max_entries
self.only_users = only_users self.only_users = only_users
super(EmailsField, self).__init__(*args, **kwargs) super(AutocompletedEmailsField, self).__init__(*args, **kwargs)
self.widget.attrs["class"] = "tokenized-field" self.widget.attrs["class"] = "tokenized-field"
self.widget.attrs["data-hint-text"] = hint_text self.widget.attrs["data-hint-text"] = hint_text
@ -41,6 +41,8 @@ class EmailsField(forms.CharField):
if isinstance(value, basestring): if isinstance(value, basestring):
addresses = self.parse_tokenized_value(value) addresses = self.parse_tokenized_value(value)
value = Email.objects.filter(address__in=addresses).select_related("person") value = Email.objects.filter(address__in=addresses).select_related("person")
if isinstance(value, Email):
value = [value]
self.widget.attrs["data-pre"] = json_emails(value) self.widget.attrs["data-pre"] = json_emails(value)
# doing this in the constructor is difficult because the URL # doing this in the constructor is difficult because the URL
@ -52,7 +54,7 @@ class EmailsField(forms.CharField):
return ",".join(e.address for e in value) return ",".join(e.address for e in value)
def clean(self, value): def clean(self, value):
value = super(EmailsField, self).clean(value) value = super(AutocompletedEmailsField, self).clean(value)
addresses = self.parse_tokenized_value(value) addresses = self.parse_tokenized_value(value)
emails = Email.objects.filter(address__in=addresses).exclude(person=None).select_related("person") emails = Email.objects.filter(address__in=addresses).exclude(person=None).select_related("person")
@ -70,3 +72,12 @@ class EmailsField(forms.CharField):
return emails return emails
class AutocompletedEmailField(AutocompletedEmailsField):
"""Version of AutocompletedEmailsField specialized to a single Email."""
def __init__(self, *args, **kwargs):
kwargs["max_entries"] = 1
super(AutocompletedEmailField, self).__init__(*args, **kwargs)
def clean(self, value):
return super(AutocompletedEmailField, self).clean(value).first()

View file

@ -8,7 +8,7 @@ from ietf.doc.models import Document, DocAlias, State
from ietf.name.models import IntendedStdLevelName, DocRelationshipName from ietf.name.models import IntendedStdLevelName, DocRelationshipName
from ietf.group.models import Group from ietf.group.models import Group
from ietf.person.models import Person, Email from ietf.person.models import Person, Email
from ietf.person.fields import EmailsField from ietf.person.fields import AutocompletedEmailField
from ietf.secr.groups.forms import get_person from ietf.secr.groups.forms import get_person
@ -132,7 +132,7 @@ class EditModelForm(forms.ModelForm):
iesg_state = forms.ModelChoiceField(queryset=State.objects.filter(type='draft-iesg'),required=False) iesg_state = forms.ModelChoiceField(queryset=State.objects.filter(type='draft-iesg'),required=False)
group = GroupModelChoiceField(required=True) group = GroupModelChoiceField(required=True)
review_by_rfc_editor = forms.BooleanField(required=False) review_by_rfc_editor = forms.BooleanField(required=False)
shepherd = EmailsField(required=False, max_entries=1) shepherd = AutocompletedEmailField(required=False)
class Meta: class Meta:
model = Document model = Document
@ -190,9 +190,6 @@ class EditModelForm(forms.ModelForm):
raise forms.ValidationError("ERROR: Draft does not exist") raise forms.ValidationError("ERROR: Draft does not exist")
return name return name
def clean_shepherd(self):
return self.cleaned_data["shepherd"].first()
def clean(self): def clean(self):
super(EditModelForm, self).clean() super(EditModelForm, self).clean()
cleaned_data = self.cleaned_data cleaned_data = self.cleaned_data

View file

@ -2,7 +2,7 @@ from django import forms
from ietf.group.models import Group from ietf.group.models import Group
from ietf.meeting.models import ResourceAssociation from ietf.meeting.models import ResourceAssociation
from ietf.person.fields import EmailsField from ietf.person.fields import AutocompletedEmailsField
# ------------------------------------------------- # -------------------------------------------------
@ -67,7 +67,7 @@ class SessionForm(forms.Form):
wg_selector3 = forms.ChoiceField(choices=WG_CHOICES,required=False) wg_selector3 = forms.ChoiceField(choices=WG_CHOICES,required=False)
third_session = forms.BooleanField(required=False) third_session = forms.BooleanField(required=False)
resources = forms.MultipleChoiceField(choices=[(x.pk,x.desc) for x in ResourceAssociation.objects.all()], widget=forms.CheckboxSelectMultiple,required=False) resources = forms.MultipleChoiceField(choices=[(x.pk,x.desc) for x in ResourceAssociation.objects.all()], widget=forms.CheckboxSelectMultiple,required=False)
bethere = EmailsField(label="Must be present", required=False) bethere = AutocompletedEmailsField(label="Must be present", required=False)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(SessionForm, self).__init__(*args, **kwargs) super(SessionForm, self).__init__(*args, **kwargs)