Checkpoint: main nomination forms use SearchableEmailField
- Legacy-Id: 10609
This commit is contained in:
parent
a2af7cfa25
commit
6bf4227974
ietf
nomcom
person
templates/nomcom
|
@ -92,7 +92,7 @@ class NomComFactory(factory.DjangoModelFactory):
|
|||
if extracted is None:
|
||||
extracted = True
|
||||
if create and extracted:
|
||||
nominees = [Nominee.objects.create(nomcom=self, email=PersonFactory().email_set.first()) for i in range(4)]
|
||||
nominees = [NomineeFactory(nomcom=self) for i in range(4)]
|
||||
positions = [PositionFactory(nomcom=self) for i in range(3)]
|
||||
|
||||
def npc(position,nominee,state_id):
|
||||
|
@ -134,6 +134,8 @@ class NomineeFactory(factory.DjangoModelFactory):
|
|||
model = Nominee
|
||||
|
||||
nomcom = factory.SubFactory(NomComFactory)
|
||||
person = factory.SubFactory(PersonFactory)
|
||||
email = factory.LazyAttribute(lambda n: n.person.email())
|
||||
|
||||
class FeedbackFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
|
|
|
@ -2,7 +2,6 @@ from django.conf import settings
|
|||
from django import forms
|
||||
from django.contrib.formtools.preview import FormPreview, AUTO_ID
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template.context import RequestContext
|
||||
|
@ -15,8 +14,10 @@ from ietf.nomcom.models import ( NomCom, Nomination, Nominee, NomineePosition,
|
|||
Position, Feedback, ReminderDates )
|
||||
from ietf.nomcom.utils import (NOMINATION_RECEIPT_TEMPLATE, FEEDBACK_RECEIPT_TEMPLATE,
|
||||
get_user_email, validate_private_key, validate_public_key,
|
||||
get_or_create_nominee, create_feedback_email)
|
||||
get_or_create_nominee, get_or_create_nominee_by_person,
|
||||
create_feedback_email)
|
||||
from ietf.person.models import Email
|
||||
from ietf.person.fields import SearchableEmailField
|
||||
from ietf.utils.fields import MultiEmailField
|
||||
from ietf.utils.mail import send_mail
|
||||
from ietf.mailtrigger.utils import gather_address_lists
|
||||
|
@ -299,7 +300,8 @@ class MergeForm(forms.Form):
|
|||
|
||||
|
||||
class NominateForm(forms.ModelForm):
|
||||
comments = forms.CharField(label="Candidate's qualifications for the position",
|
||||
candidate = SearchableEmailField(only_users=False)
|
||||
qualifications = forms.CharField(label="Candidate's qualifications for the position",
|
||||
widget=forms.Textarea())
|
||||
confirmation = forms.BooleanField(label='Email comments back to me as confirmation.',
|
||||
help_text="If you want to get a confirmation mail containing your feedback in cleartext, please check the 'email comments back to me as confirmation'.",
|
||||
|
@ -315,9 +317,10 @@ class NominateForm(forms.ModelForm):
|
|||
self.fields['nominator_email'].label = 'Nominator email'
|
||||
if self.nomcom:
|
||||
self.fields['position'].queryset = Position.objects.get_by_nomcom(self.nomcom).opened()
|
||||
self.fields['comments'].help_text = self.nomcom.initial_text
|
||||
self.fields['qualifications'].help_text = self.nomcom.initial_text
|
||||
|
||||
if not self.public:
|
||||
self.fields.pop('confirmation')
|
||||
author = get_user_email(self.user)
|
||||
if author:
|
||||
self.fields['nominator_email'].initial = author.address
|
||||
|
@ -329,21 +332,26 @@ class NominateForm(forms.ModelForm):
|
|||
has indicated they will allow NomCom to share their name as one of the people
|
||||
nominating this candidate."""
|
||||
else:
|
||||
pass
|
||||
self.fields.pop('nominator_email')
|
||||
|
||||
|
||||
def save(self, commit=True):
|
||||
# Create nomination
|
||||
nomination = super(NominateForm, self).save(commit=False)
|
||||
nominator_email = self.cleaned_data.get('nominator_email', None)
|
||||
candidate_email = self.cleaned_data['candidate_email']
|
||||
candidate_name = self.cleaned_data['candidate_name']
|
||||
## TODO - rename this candidate_email after purging the old candidate_email
|
||||
candidate = self.cleaned_data['candidate']
|
||||
##candidate_email = self.cleaned_data['candidate_email']
|
||||
##candidate_name = self.cleaned_data['candidate_name']
|
||||
position = self.cleaned_data['position']
|
||||
comments = self.cleaned_data['comments']
|
||||
confirmation = self.cleaned_data['confirmation']
|
||||
qualifications = self.cleaned_data['qualifications']
|
||||
confirmation = self.cleaned_data.get('confirmation', False)
|
||||
share_nominator = self.cleaned_data['share_nominator']
|
||||
nomcom_template_path = '/nomcom/%s/' % self.nomcom.group.acronym
|
||||
|
||||
nomination.candidate_name = candidate.person.plain_name()
|
||||
nomination.candidate_email = candidate.address
|
||||
|
||||
author = None
|
||||
if self.public:
|
||||
author = get_user_email(self.user)
|
||||
|
@ -351,11 +359,12 @@ class NominateForm(forms.ModelForm):
|
|||
if nominator_email:
|
||||
emails = Email.objects.filter(address=nominator_email)
|
||||
author = emails and emails[0] or None
|
||||
nominee = get_or_create_nominee(self.nomcom, candidate_name, candidate_email, position, author)
|
||||
##nominee = get_or_create_nominee(self.nomcom, candidate_name, candidate_email, position, author)
|
||||
nominee = get_or_create_nominee_by_person (self.nomcom, candidate.person, position, author)
|
||||
|
||||
# Complete nomination data
|
||||
feedback = Feedback.objects.create(nomcom=self.nomcom,
|
||||
comments=comments,
|
||||
comments=qualifications,
|
||||
type=FeedbackTypeName.objects.get(slug='nomina'),
|
||||
user=self.user)
|
||||
feedback.positions.add(position)
|
||||
|
@ -381,7 +390,7 @@ class NominateForm(forms.ModelForm):
|
|||
from_email = settings.NOMCOM_FROM_EMAIL
|
||||
(to_email, cc) = gather_address_lists('nomination_receipt_requested',nominator=author.address)
|
||||
context = {'nominee': nominee.email.person.name,
|
||||
'comments': comments,
|
||||
'comments': qualifications,
|
||||
'position': position.name}
|
||||
path = nomcom_template_path + NOMINATION_RECEIPT_TEMPLATE
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc)
|
||||
|
@ -390,8 +399,10 @@ class NominateForm(forms.ModelForm):
|
|||
|
||||
class Meta:
|
||||
model = Nomination
|
||||
fields = ('share_nominator', 'position', 'nominator_email', 'candidate_name',
|
||||
'candidate_email', 'candidate_phone')
|
||||
fields = ('share_nominator', 'position', 'nominator_email', 'candidate',
|
||||
'candidate_phone', 'qualifications', 'confirmation')
|
||||
##fields = ('share_nominator', 'position', 'nominator_email', 'candidate', 'candidate_name',
|
||||
## 'candidate_email', 'candidate_phone', 'qualifications', 'confirmation')
|
||||
|
||||
|
||||
class FeedbackForm(forms.ModelForm):
|
||||
|
|
|
@ -34,7 +34,7 @@ from ietf.nomcom.management.commands.send_reminders import Command, is_time_to_s
|
|||
from ietf.nomcom.factories import NomComFactory, FeedbackFactory, \
|
||||
nomcom_kwargs_for_year, provide_private_key_to_test_client, \
|
||||
key
|
||||
from ietf.person.factories import PersonFactory
|
||||
from ietf.person.factories import PersonFactory, EmailFactory
|
||||
from ietf.dbtemplate.factories import DBTemplateFactory
|
||||
from ietf.dbtemplate.models import DBTemplate
|
||||
|
||||
|
@ -481,11 +481,7 @@ class NomcomViewsTest(TestCase):
|
|||
|
||||
self.nominate_view(public=True,confirmation=True)
|
||||
|
||||
self.assertEqual(len(outbox), messages_before + 4)
|
||||
|
||||
self.assertTrue('New person' in outbox[-4]['Subject'])
|
||||
self.assertTrue('nomcomchair' in outbox[-4]['To'])
|
||||
self.assertTrue('secretariat' in outbox[-4]['To'])
|
||||
self.assertEqual(len(outbox), messages_before + 3)
|
||||
|
||||
self.assertEqual('IETF Nomination Information', outbox[-3]['Subject'])
|
||||
self.assertTrue('nominee' in outbox[-3]['To'])
|
||||
|
@ -518,15 +514,23 @@ class NomcomViewsTest(TestCase):
|
|||
login_testing_unauthorized(self, COMMUNITY_USER, self.public_nominate_url)
|
||||
empty_outbox()
|
||||
self.nominate_view(public=True)
|
||||
self.assertEqual(len(outbox), 4)
|
||||
self.assertEqual(len(outbox), 3)
|
||||
# test_public_nominate checks the other messages
|
||||
self.assertTrue('Questionnaire' in outbox[2]['Subject'])
|
||||
self.assertTrue('nominee@' in outbox[2]['To'])
|
||||
self.assertTrue('Questionnaire' in outbox[1]['Subject'])
|
||||
self.assertTrue('nominee@' in outbox[1]['To'])
|
||||
|
||||
|
||||
def nominate_view(self, *args, **kwargs):
|
||||
public = kwargs.pop('public', True)
|
||||
nominee = kwargs.pop('nominee', None)
|
||||
nominee_email = kwargs.pop('nominee_email', u'nominee@example.com')
|
||||
if not nominee:
|
||||
nominee = Email.objects.filter(address=nominee_email).first()
|
||||
if not nominee:
|
||||
nominee = EmailFactory(address=nominee_email,primary=True)
|
||||
if not nominee.person:
|
||||
nominee.person = PersonFactory()
|
||||
nominee.save()
|
||||
nominator_email = kwargs.pop('nominator_email', "%s%s" % (COMMUNITY_USER, EMAIL_DOMAIN))
|
||||
position_name = kwargs.pop('position', 'IAOC')
|
||||
confirmation = kwargs.pop('confirmation', False)
|
||||
|
@ -553,16 +557,13 @@ class NomcomViewsTest(TestCase):
|
|||
self.assertEqual(len(q("#nominate-form")), 1)
|
||||
|
||||
position = Position.objects.get(name=position_name)
|
||||
candidate_email = nominee_email
|
||||
candidate_name = u'nominee'
|
||||
comments = u'Test nominate view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.'
|
||||
candidate_phone = u'123456'
|
||||
|
||||
test_data = {'candidate_name': candidate_name,
|
||||
'candidate_email': candidate_email,
|
||||
test_data = {'candidate': nominee.pk,
|
||||
'candidate_phone': candidate_phone,
|
||||
'position': position.id,
|
||||
'comments': comments,
|
||||
'qualifications': comments,
|
||||
'confirmation': confirmation}
|
||||
if not public:
|
||||
test_data['nominator_email'] = nominator_email
|
||||
|
@ -573,12 +574,11 @@ class NomcomViewsTest(TestCase):
|
|||
self.assertContains(response, "alert-success")
|
||||
|
||||
# check objects
|
||||
email = Email.objects.get(address=candidate_email)
|
||||
Person.objects.get(name=candidate_name, address=candidate_email)
|
||||
nominee = Nominee.objects.get(email=email)
|
||||
NomineePosition.objects.get(position=position, nominee=nominee)
|
||||
## TODO - straighten this _obj vs _email naming mess out
|
||||
nominee_obj = Nominee.objects.get(email=nominee)
|
||||
NomineePosition.objects.get(position=position, nominee=nominee_obj)
|
||||
feedback = Feedback.objects.filter(positions__in=[position],
|
||||
nominees__in=[nominee],
|
||||
nominees__in=[nominee_obj],
|
||||
type=FeedbackTypeName.objects.get(slug='nomina')).latest('id')
|
||||
if public:
|
||||
self.assertEqual(feedback.author, nominator_email)
|
||||
|
@ -588,13 +588,85 @@ class NomcomViewsTest(TestCase):
|
|||
|
||||
self.assertEqual(check_comments(feedback.comments, comments, self.privatekey_file), True)
|
||||
Nomination.objects.get(position=position,
|
||||
candidate_name=candidate_name,
|
||||
candidate_email=candidate_email,
|
||||
candidate_name=nominee.person.plain_name(),
|
||||
candidate_email=nominee.address,
|
||||
candidate_phone=candidate_phone,
|
||||
nominee=nominee,
|
||||
nominee=nominee_obj,
|
||||
comments=feedback,
|
||||
nominator_email="%s%s" % (COMMUNITY_USER, EMAIL_DOMAIN))
|
||||
|
||||
## Save this for repurposing to test the to-be-created 'by name and address' form
|
||||
## def nominate_view(self, *args, **kwargs):
|
||||
## public = kwargs.pop('public', True)
|
||||
## nominee_email = kwargs.pop('nominee_email', u'nominee@example.com')
|
||||
## nominator_email = kwargs.pop('nominator_email', "%s%s" % (COMMUNITY_USER, EMAIL_DOMAIN))
|
||||
## position_name = kwargs.pop('position', 'IAOC')
|
||||
## confirmation = kwargs.pop('confirmation', False)
|
||||
##
|
||||
## if public:
|
||||
## nominate_url = self.public_nominate_url
|
||||
## else:
|
||||
## nominate_url = self.private_nominate_url
|
||||
## response = self.client.get(nominate_url)
|
||||
## self.assertEqual(response.status_code, 200)
|
||||
##
|
||||
## nomcom = get_nomcom_by_year(self.year)
|
||||
## if not nomcom.public_key:
|
||||
## q = PyQuery(response.content)
|
||||
## self.assertEqual(len(q("#nominate-form")), 0)
|
||||
##
|
||||
## # save the cert file in tmp
|
||||
## nomcom.public_key.storage.location = tempfile.gettempdir()
|
||||
## nomcom.public_key.save('cert', File(open(self.cert_file.name, 'r')))
|
||||
##
|
||||
## response = self.client.get(nominate_url)
|
||||
## self.assertEqual(response.status_code, 200)
|
||||
## q = PyQuery(response.content)
|
||||
## self.assertEqual(len(q("#nominate-form")), 1)
|
||||
##
|
||||
## position = Position.objects.get(name=position_name)
|
||||
## candidate_email = nominee_email
|
||||
## candidate_name = u'nominee'
|
||||
## comments = u'Test nominate view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.'
|
||||
## candidate_phone = u'123456'
|
||||
##
|
||||
## test_data = {'candidate_name': candidate_name,
|
||||
## 'candidate_email': candidate_email,
|
||||
## 'candidate_phone': candidate_phone,
|
||||
## 'position': position.id,
|
||||
## 'qualifications': comments,
|
||||
## 'confirmation': confirmation}
|
||||
## if not public:
|
||||
## test_data['nominator_email'] = nominator_email
|
||||
##
|
||||
## response = self.client.post(nominate_url, test_data)
|
||||
## self.assertEqual(response.status_code, 200)
|
||||
## q = PyQuery(response.content)
|
||||
## self.assertContains(response, "alert-success")
|
||||
##
|
||||
## # check objects
|
||||
## email = Email.objects.get(address=candidate_email)
|
||||
## Person.objects.get(name=candidate_name, address=candidate_email)
|
||||
## nominee = Nominee.objects.get(email=email)
|
||||
## NomineePosition.objects.get(position=position, nominee=nominee)
|
||||
## feedback = Feedback.objects.filter(positions__in=[position],
|
||||
## nominees__in=[nominee],
|
||||
## type=FeedbackTypeName.objects.get(slug='nomina')).latest('id')
|
||||
## if public:
|
||||
## self.assertEqual(feedback.author, nominator_email)
|
||||
##
|
||||
## # to check feedback comments are saved like enrypted data
|
||||
## self.assertNotEqual(feedback.comments, comments)
|
||||
##
|
||||
## self.assertEqual(check_comments(feedback.comments, comments, self.privatekey_file), True)
|
||||
## Nomination.objects.get(position=position,
|
||||
## candidate_name=candidate_name,
|
||||
## candidate_email=candidate_email,
|
||||
## candidate_phone=candidate_phone,
|
||||
## nominee=nominee,
|
||||
## comments=feedback,
|
||||
## nominator_email="%s%s" % (COMMUNITY_USER, EMAIL_DOMAIN))
|
||||
##
|
||||
def test_add_questionnaire(self):
|
||||
self.access_chair_url(self.add_questionnaire_url)
|
||||
return self.add_questionnaire()
|
||||
|
@ -656,10 +728,10 @@ class NomcomViewsTest(TestCase):
|
|||
self.feedback_view(public=True,confirmation=True)
|
||||
# feedback_view does a nomination internally: there is a lot of email related to that - tested elsewhere
|
||||
# We're interested in the confirmation receipt here
|
||||
self.assertEqual(len(outbox),4)
|
||||
self.assertEqual('NomCom comment confirmation', outbox[3]['Subject'])
|
||||
self.assertTrue('plain' in outbox[3]['To'])
|
||||
self.assertTrue(u'Comments with accents äöå' in unicode(outbox[3].get_payload(decode=True),"utf-8","replace"))
|
||||
self.assertEqual(len(outbox),3)
|
||||
self.assertEqual('NomCom comment confirmation', outbox[2]['Subject'])
|
||||
self.assertTrue('plain' in outbox[2]['To'])
|
||||
self.assertTrue(u'Comments with accents äöå' in unicode(outbox[2].get_payload(decode=True),"utf-8","replace"))
|
||||
|
||||
empty_outbox()
|
||||
self.feedback_view(public=True)
|
||||
|
|
|
@ -271,42 +271,22 @@ def send_reminder_to_nominees(nominees,type):
|
|||
return addrs
|
||||
|
||||
|
||||
def get_or_create_nominee(nomcom, candidate_name, candidate_email, position, author):
|
||||
def get_or_create_nominee_by_person(nomcom, candidate, position, author):
|
||||
from ietf.nomcom.models import Nominee, NomineePosition
|
||||
|
||||
nomcom_template_path = '/nomcom/%s/' % nomcom.group.acronym
|
||||
|
||||
# Create person and email if candidate email does't exist and send email
|
||||
email, created_email = Email.objects.get_or_create(address=candidate_email)
|
||||
if created_email:
|
||||
person = Person.objects.create(name=candidate_name,
|
||||
ascii=unaccent.asciify(candidate_name),
|
||||
address=candidate_email)
|
||||
email.person = person
|
||||
email.save()
|
||||
|
||||
# Add the nomination for a particular position
|
||||
nominee, created = Nominee.objects.get_or_create(email=email, nomcom=nomcom)
|
||||
nominee, created = Nominee.objects.get_or_create(person=candidate,email=candidate.email(), nomcom=nomcom)
|
||||
while nominee.duplicated:
|
||||
nominee = nominee.duplicated
|
||||
nominee_position, nominee_position_created = NomineePosition.objects.get_or_create(position=position, nominee=nominee)
|
||||
|
||||
if created_email:
|
||||
# send email to secretariat and nomcomchair to warn about the new person
|
||||
subject = 'New person is created'
|
||||
from_email = settings.NOMCOM_FROM_EMAIL
|
||||
(to_email, cc) = gather_address_lists('nomination_created_person',nomcom=nomcom)
|
||||
context = {'email': email.address,
|
||||
'fullname': email.person.name,
|
||||
'person_id': email.person.id}
|
||||
path = nomcom_template_path + INEXISTENT_PERSON_TEMPLATE
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc)
|
||||
|
||||
if nominee_position_created:
|
||||
# send email to nominee
|
||||
subject = 'IETF Nomination Information'
|
||||
from_email = settings.NOMCOM_FROM_EMAIL
|
||||
(to_email, cc) = gather_address_lists('nomination_new_nominee',nominee=email.address)
|
||||
(to_email, cc) = gather_address_lists('nomination_new_nominee',nominee=nominee.email.address)
|
||||
domain = Site.objects.get_current().domain
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
hash = get_hash_nominee_position(today, nominee_position.id)
|
||||
|
@ -325,7 +305,7 @@ def get_or_create_nominee(nomcom, candidate_name, candidate_email, position, aut
|
|||
today,
|
||||
hash))
|
||||
|
||||
context = {'nominee': email.person.name,
|
||||
context = {'nominee': nominee.person.name,
|
||||
'position': position.name,
|
||||
'domain': domain,
|
||||
'accept_url': accept_url,
|
||||
|
@ -338,8 +318,8 @@ def get_or_create_nominee(nomcom, candidate_name, candidate_email, position, aut
|
|||
if nomcom.send_questionnaire:
|
||||
subject = '%s Questionnaire' % position
|
||||
from_email = settings.NOMCOM_FROM_EMAIL
|
||||
(to_email, cc) = gather_address_lists('nomcom_questionnaire',nominee=email.address)
|
||||
context = {'nominee': email.person.name,
|
||||
(to_email, cc) = gather_address_lists('nomcom_questionnaire',nominee=nominee.email.address)
|
||||
context = {'nominee': nominee.person.name,
|
||||
'position': position.name}
|
||||
path = '%s%d/%s' % (nomcom_template_path,
|
||||
position.id, HEADER_QUESTIONNAIRE_TEMPLATE)
|
||||
|
@ -353,8 +333,8 @@ def get_or_create_nominee(nomcom, candidate_name, candidate_email, position, aut
|
|||
subject = 'Nomination Information'
|
||||
from_email = settings.NOMCOM_FROM_EMAIL
|
||||
(to_email, cc) = gather_address_lists('nomination_received',nomcom=nomcom)
|
||||
context = {'nominee': email.person.name,
|
||||
'nominee_email': email.address,
|
||||
context = {'nominee': nominee.person.name,
|
||||
'nominee_email': nominee.email.address,
|
||||
'position': position.name}
|
||||
|
||||
if author:
|
||||
|
@ -369,6 +349,34 @@ def get_or_create_nominee(nomcom, candidate_name, candidate_email, position, aut
|
|||
|
||||
return nominee
|
||||
|
||||
def get_or_create_nominee(nomcom, candidate_name, candidate_email, position, author):
|
||||
|
||||
## TODO: Assert here that there is no matching email or person, and change the code
|
||||
## to not possibly stomp on existing things
|
||||
|
||||
# Create person and email if candidate email does't exist and send email
|
||||
email, created_email = Email.objects.get_or_create(address=candidate_email)
|
||||
if created_email:
|
||||
person = Person.objects.create(name=candidate_name,
|
||||
ascii=unaccent.asciify(candidate_name),
|
||||
address=candidate_email)
|
||||
email.person = person
|
||||
email.save()
|
||||
|
||||
if created_email:
|
||||
# send email to secretariat and nomcomchair to warn about the new person
|
||||
subject = 'New person is created'
|
||||
from_email = settings.NOMCOM_FROM_EMAIL
|
||||
(to_email, cc) = gather_address_lists('nomination_created_person',nomcom=nomcom)
|
||||
context = {'email': email.address,
|
||||
'fullname': email.person.name,
|
||||
'person_id': email.person.id}
|
||||
nomcom_template_path = '/nomcom/%s/' % nomcom.group.acronym
|
||||
path = nomcom_template_path + INEXISTENT_PERSON_TEMPLATE
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc)
|
||||
|
||||
return get_or_create_nominee_by_person(nomcom, email.person, position, author)
|
||||
|
||||
|
||||
def getheader(header_text, default="ascii"):
|
||||
"""Decode the specified header"""
|
||||
|
|
|
@ -54,3 +54,5 @@ class EmailFactory(factory.DjangoModelFactory):
|
|||
django_get_or_create = ('address',)
|
||||
|
||||
address = '%s.%s@%s' % (factory.Faker('first_name'),factory.Faker('last_name'),factory.Faker('domain_name'))
|
||||
active = True
|
||||
primary = False
|
||||
|
|
|
@ -59,10 +59,13 @@ class PersonInfo(models.Model):
|
|||
if e:
|
||||
return e[0]
|
||||
return None
|
||||
def email_address(self):
|
||||
def email(self):
|
||||
e = self.email_set.filter(primary=True).first()
|
||||
if not e:
|
||||
e = self.email_set.filter(active=True).order_by("-time").first()
|
||||
return e
|
||||
def email_address(self):
|
||||
e = self.email()
|
||||
if e:
|
||||
return e.address
|
||||
else:
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
{% extends "nomcom/nomcom_private_base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load nomcom_tags %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" href="{% static 'select2/select2.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'select2-bootstrap-css/select2-bootstrap.min.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block subtitle %} - Nominate{% endblock %}
|
||||
|
||||
{% block nomcom_content %}
|
||||
|
@ -30,3 +36,8 @@
|
|||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'select2/select2.min.js' %}"></script>
|
||||
<script src="{% static 'ietf/js/select2-field.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
{% extends "nomcom/nomcom_public_base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load nomcom_tags %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" href="{% static 'select2/select2.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'select2-bootstrap-css/select2-bootstrap.min.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block subtitle %} - Nominate{% endblock %}
|
||||
|
||||
{% block nomcom_content %}
|
||||
|
@ -26,3 +32,8 @@
|
|||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'select2/select2.min.js' %}"></script>
|
||||
<script src="{% static 'ietf/js/select2-field.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in a new issue