Skip to content

Commit 68d4a58

Browse files
committed
The fourth (and last?) take on a form from multiple models,
using pretty much the same template as for a non-form view. This solution is less hackish than the previous one which used the form.as_table() rendering of a form, and then split the resulting html in chunks. Instead, '''all''' the html has been moved out to a formfield template, and a custom form class is generated which will render the form elements using an indicated template. * Add form factory in utils.py (an old version which still has html in the code is there for history, but will be removed * Changes in ipr/views.py:new(), now subclassing one form with some class members being other form instances, matching the members used for the show() view * A fix in ipr/models, making an email field use models.EmailField * Reverting a number of changes in ipr/details.html which aren't needed any more, as well as in ipr/new.html; and adding ipr/formfield.html - Legacy-Id: 104
1 parent 8082998 commit 68d4a58

7 files changed

Lines changed: 132 additions & 58 deletions

File tree

ietf/ipr/feeds.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
class LatestIprDisclosures(Feed):
77
feed_type = Atom1Feed
8-
feed_url = "/feeds/ipr/"
98
title = "IPR Disclosures to the IETF"
109
link = "/ipr/"
1110
description = "Updates on new IPR Disclosures made to the IETF."
1211
language = "en"
12+
feed_url = "/feeds/ipr/"
1313

1414
def items(self):
1515
return IprDetail.objects.order_by('-submitted_date')[:5]

ietf/ipr/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class IprContact(models.Model):
128128
address2 = models.CharField(blank=True, maxlength=255)
129129
telephone = models.CharField(maxlength=25)
130130
fax = models.CharField(blank=True, maxlength=25)
131-
email = models.CharField(maxlength=255)
131+
email = models.EmailField(maxlength=255)
132132
def __str__(self):
133133
return self.name
134134
class Meta:

ietf/ipr/views.py

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.shortcuts import render_to_response as render
33
import django.newforms as forms
44
import ietf.utils
5+
import syslog
56

67
def default(request):
78
"""Default page, with links to sub-pages"""
@@ -61,35 +62,27 @@ def update(request, ipr_id=None):
6162
return show(request, ipr_id)
6263

6364
def new(request, type):
64-
"""Form to make a new IPR disclosure"""
65+
"""Make a new IPR disclosure"""
6566
debug = ""
66-
sections = {
67-
"section1": "p_h_legal_name ",
68-
"section2": "ph_name ph_title ph_department ph_address1 ph_address2 ph_telephone ph_fax ph_email",
69-
"section3": "ietf_name ietf_title ietf_department ietf_address1 ietf_address2 ietf_telephone ietf_fax ietf_email",
70-
"section4": "rfclist draftlist other_designations",
71-
"section5": "p_applications date_applied country selecttype p_notes discloser_identify",
72-
"section6": "licensing_option stdonly_license comments lic_checkbox selectowned",
73-
"section7": "sub_name sub_title sub_department sub_address1 sub_address2 sub_telephone sub_fax sub_email",
74-
"section8": "other_notes",
75-
"ignore" : "document_title rfc_number id_document_tag submitted_date status " +
76-
"old_ipr_url additional_old_title1 additional_old_title2 " +
77-
"additional_old_url1 additional_old_url2 update_notified_date",
78-
}
79-
IprForm = forms.form_for_model(models.IprDetail, formfield_callback=detail_field_fixup)
80-
ContactForm = forms.form_for_model(models.IprContact)
81-
82-
# It would be nicer if we could use mixin subclassing, but that won't
83-
# work with multiple classes with the same elements.
84-
for prefix in ["ph", "ietf", "sub"]:
85-
for field in ContactForm.base_fields:
86-
IprForm.base_fields[prefix + "_" + field] = ContactForm.base_fields[field]
87-
88-
# Some extra fields which will get post-processing to generate the IprRfcs
89-
# and IprDrafts entries which go into the database:
90-
IprForm.base_fields["rfclist"] = forms.CharField(required=False)
91-
IprForm.base_fields["draftlist"] = forms.CharField(required=False)
92-
IprForm.base_fields["stdonly_license"] = forms.BooleanField(required=False)
67+
68+
# CustomForm = mk_formatting_form(format="%(errors)s%(field)s%(help_text)s")
69+
CustomForm = ietf.utils.makeFormattingForm(template="ipr/formfield.html")
70+
BaseIprForm = forms.form_for_model(models.IprDetail, form=CustomForm, formfield_callback=detail_field_fixup)
71+
ContactForm = forms.form_for_model(models.IprContact, form=CustomForm)
72+
73+
# Some subclassing:
74+
class IprForm(BaseIprForm):
75+
holder_contact = None
76+
rfclist = forms.CharField(required=False)
77+
draftlist = forms.CharField(required=False)
78+
stdonly_license = forms.BooleanField(required=False)
79+
def __init__(self, *args, **kw):
80+
self.base_fields["holder_contact"] = ContactForm(prefix="ph", *args, **kw)
81+
# syslog.syslog("IprForm.__init__: holder_contact: %s" % repr(self.base_fields["holder_contact"]))
82+
83+
self.base_fields["ietf_contact"] = ContactForm(prefix="ietf", *args, **kw)
84+
self.base_fields["submitter"] = ContactForm(prefix="sub", *args, **kw)
85+
BaseIprForm.__init__(self, *args, **kw)
9386

9487
if request.method == 'POST':
9588
form = IprForm(request.POST)
@@ -99,9 +92,7 @@ def new(request, type):
9992
else:
10093
form = IprForm()
10194

102-
blocks = ietf.utils.split_form(form.as_table(), sections )
103-
104-
return render("ipr/new_%s.html" % type, {"ipr": form, "form": blocks})
95+
return render("ipr/new_%s.html" % type, {"ipr": form, "debug": ""})
10596

10697
def detail_field_fixup(field):
10798
if field.name == "licensing_option":

ietf/templates/ipr/details.html

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
.ipr { width: 101ex; }
77
.even { }
88
.odd { }
9-
.even th { background: #aaa; color: #336; font-family: Arial, sans-serif; font-size: small; text-align: left; font-weight: bold; }
10-
.odd th { background: #cca; color: #336; font-family: Arial, sans-serif; font-size: small; text-align: left; font-weight: bold; }
11-
.even td { background: #eee; color: #000; font-family: Arial, sans-serif; font-size: small; text-align: left; vertical-align: top; }
12-
.odd td { background: #eed; color: #000; font-family: Arial, sans-serif; font-size: small; text-align: left; vertical-align: top; }
9+
.even td,th { background: #eee; color: #000; font-family: Arial, sans-serif; font-size: small; text-align: left; vertical-align: top; }
10+
.odd td,th { background: #eed; color: #000; font-family: Arial, sans-serif; font-size: small; text-align: left; vertical-align: top; }
11+
.even tr:first-child th { background: #aaa; color: #336; font-family: Arial, sans-serif; font-size: small; text-align: left; font-weight: bold; }
12+
.odd tr:first-child th { background: #cca; color: #336; font-family: Arial, sans-serif; font-size: small; text-align: left; font-weight: bold; }
1313
table.ipr {
1414
padding:2px;
1515
border-width:1px;
@@ -19,14 +19,16 @@
1919
.ipr th { border: 0px; margin: 0px; padding: 4px; }
2020
.ipr td { border: 0px; margin: 0px; padding: 4px; }
2121
td.fixwidth { width: 14ex; }
22-
.ipr ul { margin-left: -6ex; list-style-type: none; }
22+
td.inset{ padding-left: 14ex; }
23+
.ipr ul { padding-left: -2ex; list-style-type: none; }
2324
h4.ipr { text-align: center; }
2425
input { width: 72ex; font-family: sans-serif; font-size: 11pt; font-weight: normal; }
2526
input[type="radio"] { width: auto; }
2627
input[type="checkbox"] { width: auto; }
2728
input[type="submit"] { width: auto; }
2829
textarea { width: 72ex; height: 5em; font-family: sans-serif; font-size: 11pt; font-weight: normal; }
2930
.required { color: red; }
31+
.errorlist { background: red; padding: 0 0 0 2px; border: 0px; margin: 0px; }
3032
</style>
3133

3234
{% block top_info %}
@@ -147,7 +149,6 @@ <h3>{{ ipr.document_title }}</h3>
147149

148150

149151
{% block section3 %}
150-
{% if not ipr.is_bound or not ipr.old_ipr_url %}
151152
<blockquote class="{% cycle parity %}">
152153
<table border="0" cellpadding="0" cellspacing="0" class="ipr person">
153154
<tr>
@@ -157,7 +158,7 @@ <h3>{{ ipr.document_title }}</h3>
157158
</th>
158159
</tr>
159160
{% block section3_data %}
160-
{% if ipr.unbond_form or ipr.ietf_contact.name %}
161+
{% if not ipr.is_bound or ipr.ietf_contact.name %}
161162
<tr><td class="fixwidth">Name:</td> <td><b>{{ ipr.ietf_contact.name }}</b></td></tr>
162163
<tr><td class="fixwidth">Title:</td> <td><b>{{ ipr.ietf_contact.title }}</b></td></tr>
163164
<tr><td class="fixwidth">Department:</td> <td><b>{{ ipr.ietf_contact.department }}</b></td></tr>
@@ -172,9 +173,6 @@ <h3>{{ ipr.document_title }}</h3>
172173
{% endblock %}
173174
</table>
174175
</blockquote>
175-
{% else %}
176-
<!-- Not showing section {% cycle section %} -->
177-
{% endif %}
178176
{% endblock %}
179177

180178

@@ -203,8 +201,6 @@ <h3>{{ ipr.document_title }}</h3>
203201
</blockquote>
204202
{% endblock %}
205203

206-
{% if not ipr.is_bound or not ipr.old_ipr_url %}
207-
208204
{% block section5 %}
209205
<blockquote class="{% cycle parity %}">
210206
<table border="0" cellpadding="0" cellspacing="0" class="ipr">
@@ -245,9 +241,9 @@ <h3>{{ ipr.document_title }}</h3>
245241
</td>
246242
</tr>
247243
{% if ipr.discloser_identify %}
248-
<tr><td class="fixwidth"> </td><td><b>{{ ipr.discloser_identify|escape|linebreaks }}</b></td></tr>
244+
<tr><td colspan="2" class="inset"><b>{{ ipr.discloser_identify|escape|linebreaks }}</b></td></tr>
249245
{% else %}
250-
<tr><td class="fixwidth"> </td><td><i>No information submitted</i></td></tr>
246+
<tr><td colspan="2" class="inset"></span><i>No information submitted</i></td></tr>
251247
{% endif %}
252248
{% endblock %}
253249
{% else %}
@@ -370,7 +366,6 @@ <h3>{{ ipr.document_title }}</h3>
370366
</blockquote>
371367
{% endblock %}
372368

373-
{% endif %}
374369
{{ debug }}
375370

376371
{% block bot_info %}

ietf/templates/ipr/formfield.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{% if errors %}
2+
<ul>
3+
{% for error in errors %}
4+
<li>{{ errorr }}</li>
5+
{% endfor %}
6+
</ul>
7+
{% endif %}
8+
{{ field }}{{ help_text }}

ietf/templates/ipr/new.html

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% extends "ipr/details.html" %}
1+
{% extends "ipr/details.html" %}
22
{% block title %}IPR Disclosure Page{% endblock %}
33
{% block top_info %}
44
{% if not ipr %}
@@ -53,17 +53,9 @@ <h4 class="ipr">The Patent Disclosure and Licensing Declaration Template for {{
5353
</p>
5454
</blockquote>
5555
{% endif %}
56-
<form>
56+
<form method="post">
5757
{% endblock %}
5858

59-
{% block section1_data %}{{ form.section1 }}{% endblock %}
60-
{% block section2_data %}{{ form.section2 }}{% endblock %}
61-
{% block section3_data %}{{ form.section3 }}{% endblock %}
62-
{% block section4_data %}{{ form.section4 }}{% endblock %}
63-
{% block section5_data %}{{ form.section5 }}{% endblock %}
64-
{% block section6_data %}{{ form.section6 }}{% endblock %}
65-
{% block section7_data %}{{ form.section7 }}{% endblock %}
66-
{% block section8_data %}{{ form.section8 }}{% endblock %}
6759
{% block bot_info %}
6860
<center><input type="submit" name="submit" value="Submit"></center>
6961
</form>

ietf/utils.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,91 @@ def split_form(html, blocks):
176176
output[block] = "\n".join(output[block])
177177

178178
return output
179+
180+
def mk_formatting_form(format="<span>%(label)s</span><span><ul>%(errors)s</ul>%(field)s%(help_text)s</span>",
181+
labelfmt="%s:", fieldfmt="%s", errfmt="<li>%s</li>", error_wrap="<ul>%s</ul>", helpfmt="%s"):
182+
"""Create a form class which formats its fields using the provided format string(s).
183+
184+
The format string may use these format specifications:
185+
%(label)s
186+
%(errors)s
187+
%(field)s
188+
%(help_text)s
189+
190+
The individual sub-formats must contain "%s" if defined.
191+
"""
192+
class FormattingForm(forms.BaseForm):
193+
_format = format
194+
_labelfmt = labelfmt
195+
_fieldfmt = fieldfmt
196+
_errfmt = errfmt
197+
_errwrap = error_wrap
198+
_helpfmt = helpfmt
199+
def __getitem__(self, name):
200+
"Returns a BoundField with the given name."
201+
# syslog.syslog("FormattingForm.__getitem__(%s)" % (name))
202+
try:
203+
field = self.fields[name]
204+
except KeyError:
205+
# syslog.syslog("Exception: FormattingForm.__getitem__: Key %r not found" % (name))
206+
raise KeyError('Key %r not found in Form' % name)
207+
208+
if not isinstance(field, forms.fields.Field):
209+
return field
210+
211+
try:
212+
bf = forms.forms.BoundField(self, field, name)
213+
except Exception, e:
214+
# syslog.syslog("Exception: FormattingForm.__getitem__: %s" % (e))
215+
raise Exception(e)
216+
217+
try:
218+
error_txt = "".join([self._errfmt % escape(error) for error in bf.errors])
219+
error_txt = error_txt and self._errwrap % error_txt
220+
label_txt = bf.label and self._labelfmt % bf.label_tag(escape(bf.label)) or ''
221+
field_txt = self._fieldfmt % unicode(bf)
222+
help_txt = field.help_text and self._helpfmt % field.help_text or u''
223+
224+
except Exception, e:
225+
# syslog.syslog("Exception: FormattingForm.__getitem__: %s" % (e))
226+
raise Exception(e)
227+
228+
return self._format % {"label":label_txt, "errors":error_txt, "field":field_txt, "help_text":help_txt}
229+
230+
def add_prefix(self, field_name):
231+
return self.prefix and ('%s_%s' % (self.prefix, field_name)) or field_name
232+
233+
234+
# syslog.syslog("Created new FormattingForm class: %s" % FormattingForm)
235+
236+
return FormattingForm
237+
238+
239+
def makeFormattingForm(template=None):
240+
"""Create a form class which formats its fields using the provided template
241+
242+
The template is provided with a dictionary containing the following keys, value
243+
pairs:
244+
245+
"label": field label, if any,
246+
"errors": list of errors, if any,
247+
"field": widget rendering for an unbound form / field value for a bound form,
248+
"help_text": field help text, if any
249+
250+
"""
251+
from django.template import loader
252+
import django.newforms as forms
253+
254+
class FormattingForm(forms.BaseForm):
255+
_template = template
256+
def __getitem__(self, name):
257+
"Returns a BoundField with the given name."
258+
try:
259+
field = self.fields[name]
260+
except KeyError:
261+
raise KeyError('Key %r not found in Form' % name)
262+
if not isinstance(field, forms.fields.Field):
263+
return field
264+
bf = forms.forms.BoundField(self, field, name)
265+
return loader.render_to_string(self._template, { "errors": bf.errors, "label": bf.label, "field": unicode(bf), "help_text": field.help_text })
266+
return FormattingForm

0 commit comments

Comments
 (0)