* Added a new funtion in utils.py: split_form()
* Re-wrote the IPR declaration form using form.to_table() and the split_form() function in order to get sub-blocks of the form which could easily be used with the existing IPR detail display templates. How to merge forms from multiple models took some thinking; since the forms have a common ancestor, multiple inheritance doesn't preserve the form data. In the end the merging didn't turn out too horrible. See ipr.views.new(). * Changed the IprDetail model; first to specify editable=False for all fieleds which shouldn't be shown in the form, but this has the drawback of also removing them from the admin page form. Simply bagging them in an un-used sub block with split_form() works fine. * Changed the URLs for IPR by-date some again * Updated the ipr/new* templates to use the form sub-blocks - Legacy-Id: 97
This commit is contained in:
parent
5872696834
commit
c2c08c9edc
|
@ -46,10 +46,10 @@ class IprLicensing(models.Model):
|
|||
|
||||
class IprDetail(models.Model):
|
||||
ipr_id = models.AutoField(primary_key=True)
|
||||
p_h_legal_name = models.CharField("Patent Holder's Legal Name", blank=True, maxlength=255)
|
||||
p_h_legal_name = models.CharField("Legal Name", blank=True, maxlength=255)
|
||||
document_title = models.CharField(blank=True, maxlength=255)
|
||||
rfc_number = models.IntegerField(null=True, blank=True) # always NULL
|
||||
id_document_tag = models.IntegerField(null=True, blank=True) # always NULL
|
||||
rfc_number = models.IntegerField(null=True, editable=False, blank=True) # always NULL
|
||||
id_document_tag = models.IntegerField(null=True, editable=False, blank=True) # always NULL
|
||||
other_designations = models.CharField(blank=True, maxlength=255)
|
||||
p_applications = models.TextField(blank=True, maxlength=255)
|
||||
date_applied = models.CharField(blank=True, maxlength=255)
|
||||
|
@ -69,14 +69,13 @@ class IprDetail(models.Model):
|
|||
additional_old_url2 = models.CharField(blank=True, maxlength=255)
|
||||
country = models.CharField(blank=True, maxlength=100)
|
||||
p_notes = models.TextField(blank=True)
|
||||
third_party = models.BooleanField()
|
||||
lic_opt_a_sub = models.IntegerField(choices=STDONLY_CHOICES)
|
||||
lic_opt_b_sub = models.IntegerField(choices=STDONLY_CHOICES)
|
||||
lic_opt_c_sub = models.IntegerField(choices=STDONLY_CHOICES)
|
||||
generic = models.BooleanField()
|
||||
# I don't understand selectowned, it looks like it should be a boolean field.
|
||||
third_party = models.BooleanField(editable=False)
|
||||
lic_opt_a_sub = models.IntegerField(editable=False, choices=STDONLY_CHOICES)
|
||||
lic_opt_b_sub = models.IntegerField(editable=False, choices=STDONLY_CHOICES)
|
||||
lic_opt_c_sub = models.IntegerField(editable=False, choices=STDONLY_CHOICES)
|
||||
generic = models.BooleanField(editable=False)
|
||||
selectowned = models.IntegerField(null=True, blank=True, choices=SELECT_CHOICES)
|
||||
comply = models.BooleanField()
|
||||
comply = models.BooleanField(editable=False)
|
||||
lic_checkbox = models.BooleanField()
|
||||
update_notified_date = models.DateField(null=True, blank=True)
|
||||
def __str__(self):
|
||||
|
@ -103,16 +102,16 @@ class IprContact(models.Model):
|
|||
('3', 'Submitter Contact'),
|
||||
)
|
||||
contact_id = models.AutoField(primary_key=True)
|
||||
ipr = models.ForeignKey(IprDetail, raw_id_admin=True, related_name="contact")
|
||||
contact_type = models.IntegerField(choices=TYPE_CHOICES)
|
||||
ipr = models.ForeignKey(IprDetail, raw_id_admin=True, editable=False, related_name="contact")
|
||||
contact_type = models.IntegerField(editable=False, choices=TYPE_CHOICES)
|
||||
name = models.CharField(maxlength=255)
|
||||
title = models.CharField(blank=True, maxlength=255)
|
||||
department = models.CharField(blank=True, maxlength=255)
|
||||
address1 = models.CharField(blank=True, maxlength=255)
|
||||
address2 = models.CharField(blank=True, maxlength=255)
|
||||
telephone = models.CharField(maxlength=25)
|
||||
fax = models.CharField(blank=True, maxlength=25)
|
||||
email = models.CharField(maxlength=255)
|
||||
address1 = models.CharField(blank=True, maxlength=255)
|
||||
address2 = models.CharField(blank=True, maxlength=255)
|
||||
def __str__(self):
|
||||
return self.name
|
||||
class Meta:
|
||||
|
|
|
@ -14,6 +14,7 @@ queryset = models.IprDetail.objects.all()
|
|||
archive = {'queryset':queryset, 'date_field': 'submitted_date', 'allow_empty':True }
|
||||
|
||||
urlpatterns += patterns('django.views.generic.date_based',
|
||||
(r'^by-date/$', 'archive_index', archive),
|
||||
(r'^(?P<year>\d{4})/$', 'archive_year', archive),
|
||||
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'archive_month', archive),
|
||||
)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import models
|
||||
from django.shortcuts import render_to_response as render
|
||||
import django.newforms as forms
|
||||
import ietf.utils
|
||||
|
||||
def default(request):
|
||||
"""Default page, with links to sub-pages"""
|
||||
|
@ -62,35 +63,45 @@ def update(request, ipr_id=None):
|
|||
def new(request, type):
|
||||
"""Form to make a new IPR disclosure"""
|
||||
debug = ""
|
||||
|
||||
sections = {
|
||||
"section1": "p_h_legal_name ",
|
||||
"section2": "ph_name ph_title ph_department ph_address1 ph_address2 ph_telephone ph_fax ph_email",
|
||||
"section3": "ietf_name ietf_title ietf_department ietf_address1 ietf_address2 ietf_telephone ietf_fax ietf_email",
|
||||
"section4": "rfclist draftlist other_designations",
|
||||
"section5": "p_applications date_applied country selecttype p_notes discloser_identify",
|
||||
"section6": "licensing_option stdonly_license comments lic_checkbox selectowned",
|
||||
"section7": "sub_name sub_title sub_department sub_address1 sub_address2 sub_telephone sub_fax sub_email",
|
||||
"section8": "other_notes",
|
||||
"ignore" : "document_title rfc_number id_document_tag submitted_date status " +
|
||||
"old_ipr_url additional_old_title1 additional_old_title2 " +
|
||||
"additional_old_url1 additional_old_url2 update_notified_date",
|
||||
}
|
||||
IprForm = forms.form_for_model(models.IprDetail, formfield_callback=detail_field_fixup)
|
||||
ContactForm = forms.form_for_model(models.IprContact)
|
||||
|
||||
# It would be nicer if we could use mixin subclassing, but that won't
|
||||
# work with multiple classes with the same elements.
|
||||
for prefix in ["ph", "ietf", "sub"]:
|
||||
for field in ContactForm.base_fields:
|
||||
IprForm.base_fields[prefix + "_" + field] = ContactForm.base_fields[field]
|
||||
|
||||
# Some extra fields which will get post-processing to generate the IprRfcs
|
||||
# and IprDrafts entries which go into the database:
|
||||
IprForm.base_fields["rfclist"] = forms.CharField(required=False)
|
||||
IprForm.base_fields["draftlist"] = forms.CharField(required=False)
|
||||
IprForm.base_fields["stdonly_license"] = forms.BooleanField(required=False)
|
||||
|
||||
ContactForm = forms.form_for_model(models.IprContact)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = IprForm(request.POST)
|
||||
|
||||
form.holder_contact = ContactForm(request.POST, prefix="ph")
|
||||
form.ietf_contact = ContactForm(request.POST, prefix="ietf")
|
||||
form.submitter = ContactForm(request.POST, prefix="sub")
|
||||
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return HttpResponseRedirect("/ipr/")
|
||||
else:
|
||||
form = IprForm()
|
||||
form.holder_contact = ContactForm(prefix="ph")
|
||||
form.ietf_contact = ContactForm(prefix="ietf")
|
||||
form.submitter = ContactForm(prefix="sub")
|
||||
|
||||
form.unbound_form = not form.is_bound
|
||||
form.disclosure_type = type.capitalize()
|
||||
return render("ipr/new_%s.html" % type, {"ipr": form, "debug": debug, })
|
||||
blocks = ietf.utils.split_form(form.as_table(), sections )
|
||||
|
||||
return render("ipr/new_%s.html" % type, {"ipr": form, "form": blocks})
|
||||
|
||||
def detail_field_fixup(field):
|
||||
if field.name == "licensing_option":
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
input { width: 72ex; font-family: sans-serif; font-size: 11pt; font-weight: normal; }
|
||||
input[type="radio"] { width: auto; }
|
||||
input[type="checkbox"] { width: auto; }
|
||||
input[type="submit"] { width: auto; }
|
||||
textarea { width: 72ex; height: 5em; font-family: sans-serif; font-size: 11pt; font-weight: normal; }
|
||||
.required { color: red; }
|
||||
</style>
|
||||
|
@ -113,7 +114,9 @@
|
|||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
{% block section1_data %}
|
||||
<td class="fixwidth">Legal Name:</td> <td><b> {{ ipr.p_h_legal_name }} </b></td>
|
||||
{% endblock %}
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
|
@ -128,6 +131,7 @@
|
|||
Patent Holder's Contact for License Application
|
||||
</th>
|
||||
</tr>
|
||||
{% block section2_data %}
|
||||
<tr><td class="fixwidth">Name:</td> <td><b>{{ ipr.holder_contact.name }}</b></td></tr>
|
||||
<tr><td class="fixwidth">Title:</td> <td><b>{{ ipr.holder_contact.title }}</b></td></tr>
|
||||
<tr><td class="fixwidth">Department:</td> <td><b>{{ ipr.holder_contact.department }}</b></td></tr>
|
||||
|
@ -136,13 +140,14 @@
|
|||
<tr><td class="fixwidth">Telephone:</td> <td><b>{{ ipr.holder_contact.telephone }}</b></td></tr>
|
||||
<tr><td class="fixwidth">Fax:</td> <td><b>{{ ipr.holder_contact.fax }}</b></td></tr>
|
||||
<tr><td class="fixwidth">Email:</td> <td><b>{{ ipr.holder_contact.email }}</b></td></tr>
|
||||
{% endblock %}
|
||||
</table>
|
||||
</blockquote>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block section3 %}
|
||||
{% if ipr.unbound_form or not ipr.old_ipr_url %}
|
||||
{% if not ipr.is_bound or not ipr.old_ipr_url %}
|
||||
<blockquote class="{% cycle parity %}">
|
||||
<table border="0" cellpadding="0" cellspacing="0" class="ipr person">
|
||||
<tr>
|
||||
|
@ -151,6 +156,7 @@
|
|||
Contact Information for the IETF Participant Whose Personal Belief Triggered this Disclosure:
|
||||
</th>
|
||||
</tr>
|
||||
{% block section3_data %}
|
||||
{% if ipr.unbond_form or ipr.ietf_contact.name %}
|
||||
<tr><td class="fixwidth">Name:</td> <td><b>{{ ipr.ietf_contact.name }}</b></td></tr>
|
||||
<tr><td class="fixwidth">Title:</td> <td><b>{{ ipr.ietf_contact.title }}</b></td></tr>
|
||||
|
@ -163,6 +169,7 @@
|
|||
{% else %}
|
||||
<tr><td colspan="2"><i>No information submitted</td></tr>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</table>
|
||||
</blockquote>
|
||||
{% else %}
|
||||
|
@ -180,29 +187,23 @@
|
|||
IETF Document or Other Contribution to Which this IPR Disclosure Relates:
|
||||
</th>
|
||||
</tr>
|
||||
{% if ipr.unbound_form %}
|
||||
<tr><td class="fixwidth">RFC Number(s) (Numeric value only):</td><td>{{ ipr.rfclist }}</td></tr>
|
||||
{% else %}
|
||||
{% block section4_data %}
|
||||
{% for rfc in ipr.rfcs.all %}
|
||||
<tr><td class="fixwidth"><b>RFC {{ rfc.rfc_number.rfc_number }}:</b></td><td><b>"{{ rfc.rfc_number.rfc_name }}"</b></td></tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<!-- XXX: Omitting code to display information from the rfc_number field of ipr here, as it's always NULL in the database today. -->
|
||||
{% if ipr.unbound_form %}
|
||||
<tr><td class="fixwidth">I-D filename(s) (draft-...):</td><td><b>{{ ipr.draftlist }}</b></td></tr>
|
||||
{% else %}
|
||||
<!-- XXX: Omitting code to display information from the rfc_number field of ipr here, as it's always NULL in the database today. -->
|
||||
{% for draft in ipr.drafts.all %}
|
||||
<tr><td class="fixwidth">Internet-Draft:</td><td><b>"{{ draft.document.id_document_name }}"<br />(<tt><big>{{ draft.document.filename }}-{{ draft.document.revision }}</big></tt>)</b></td></tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if ipr.unbound_form or ipr.other_designations %}
|
||||
{% if ipr.other_designations %}
|
||||
<tr><td class="fixwidth">Designations for Other Contributions:</td><td><b>{{ ipr.other_designations }}</b></td></tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</table>
|
||||
</blockquote>
|
||||
{% endblock %}
|
||||
|
||||
{% if ipr.unbound_form or not ipr.old_ipr_url %}
|
||||
{% if not ipr.is_bound or not ipr.old_ipr_url %}
|
||||
|
||||
{% block section5 %}
|
||||
<blockquote class="{% cycle parity %}">
|
||||
|
@ -214,34 +215,24 @@
|
|||
applications required to be disclosed by Section 6 of RFC 3979)
|
||||
</th>
|
||||
</tr>
|
||||
{% if ipr.unbound_form or ipr.p_applications or ipr.p_notes %}
|
||||
<tr>
|
||||
<td colspan="2"><i>
|
||||
A. For granted patents or published pending patent applications,
|
||||
please provide the following information:</i></td>
|
||||
</tr>
|
||||
<tr><td>Patent, Serial, Publication, Registration,
|
||||
or Application/File number(s):</td><td><b>{{ ipr.p_applications }}</b></td></tr>
|
||||
<tr><td>Date(s) granted or applied for: </td><td><b>{{ ipr.date_applied }}</b></td></tr>
|
||||
<tr><td>Country: </td><td><b>{{ ipr.country }}</b></td></tr>
|
||||
{% if ipr.unbound_form %}
|
||||
<tr><td>Additional Notes: </td><td><b>{{ ipr.p_notes }}</b></td></tr>
|
||||
{% else %}
|
||||
<tr><td>Additional Notes: </td><td><b>{{ ipr.p_notes|escape|linebreaks }}</b></td></tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td colspan="2"><i>
|
||||
B. Does this disclosure relate to an unpublished pending patent
|
||||
application?: </i>
|
||||
<b>{{ ipr.get_selecttype_display }}</b>
|
||||
</tr>
|
||||
{% if ipr.unbound_form %}
|
||||
<tr><td></td>
|
||||
<td>
|
||||
{{ ipr.selecttype }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% block section5_data %}
|
||||
{% if ipr.p_applications or ipr.p_notes %}
|
||||
<tr>
|
||||
<td colspan="2"><i>
|
||||
A. For granted patents or published pending patent applications,
|
||||
please provide the following information:</i></td>
|
||||
</tr>
|
||||
<tr><td>Patent, Serial, Publication, Registration,
|
||||
or Application/File number(s):</td><td><b>{{ ipr.p_applications }}</b></td></tr>
|
||||
<tr><td>Date(s) granted or applied for: </td><td><b>{{ ipr.date_applied }}</b></td></tr>
|
||||
<tr><td>Country: </td><td><b>{{ ipr.country }}</b></td></tr>
|
||||
<tr><td>Additional Notes: </td><td><b>{{ ipr.p_notes|escape|linebreaks }}</b></td></tr>
|
||||
<tr>
|
||||
<td colspan="2"><i>
|
||||
B. Does this disclosure relate to an unpublished pending patent
|
||||
application?: </i>
|
||||
<b>{{ ipr.get_selecttype_display }}</b>
|
||||
</tr>
|
||||
{% block clause5c %}
|
||||
<tr>
|
||||
<td colspan="2"><i>
|
||||
|
@ -253,19 +244,16 @@
|
|||
covered:</i>
|
||||
</td>
|
||||
</tr>
|
||||
{% if ipr.unbound_form %}
|
||||
<tr><td class="fixwidth"> </td><td><b>{{ ipr.discloser_identify }}</b></td></tr>
|
||||
{% if ipr.discloser_identify %}
|
||||
<tr><td class="fixwidth"> </td><td><b>{{ ipr.discloser_identify|escape|linebreaks }}</b></td></tr>
|
||||
{% else %}
|
||||
{% if ipr.discloser_identify %}
|
||||
<tr><td class="fixwidth"> </td><td><b>{{ ipr.discloser_identify|escape|linebreaks }}</b></td></tr>
|
||||
{% else %}
|
||||
<tr><td class="fixwidth"> </td><td><i>No information submitted</i></td></tr>
|
||||
{% endif %}
|
||||
<tr><td class="fixwidth"> </td><td><i>No information submitted</i></td></tr>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% else %}
|
||||
<tr><td class="fixwidth"></td><td><b>This disclosure relates to an unpublished pending patent application.</b></td></tr>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</table>
|
||||
</blockquote>
|
||||
{% endblock %}
|
||||
|
@ -290,18 +278,13 @@
|
|||
specification, is as follows(select one licensing declaration option only):</i>
|
||||
</td>
|
||||
</tr>
|
||||
{% block section6_data %}
|
||||
<tr>
|
||||
<td> </td><td>
|
||||
{% if ipr.unbound_form %}
|
||||
{{ ipr.licensing_option }}
|
||||
{{ ipr.stdonly_license }}
|
||||
This licensing declaration is limited solely to standards-track IETF documents.
|
||||
{% else %}
|
||||
<b>{{ ipr.get_licensing_option_display }}<br/>
|
||||
{{ ipr.get_lic_opt_a_sub_display }}
|
||||
{{ ipr.get_lic_opt_b_sub_display }}
|
||||
{{ ipr.get_lic_opt_c_sub_display }}</b>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -309,20 +292,15 @@
|
|||
<i>Licensing information, comments, notes, or URL for further information:</i>
|
||||
</td>
|
||||
</tr>
|
||||
{% if ipr.unbound_form %}
|
||||
<tr><td class="fixwidth"> </td><td><b>{{ ipr.comments }}</b></td></tr>
|
||||
{% if ipr.comments %}
|
||||
<tr><td class="fixwidth"> </td><td><b>{{ ipr.comments|escape|linebreaks }}</b></td></tr>
|
||||
{% else %}
|
||||
{% if ipr.comments %}
|
||||
<tr><td class="fixwidth"> </td><td><b>{{ ipr.comments|escape|linebreaks }}</b></td></tr>
|
||||
{% else %}
|
||||
<tr><td class="fixwidth"> </td><td><i>No information submitted</td></tr>
|
||||
{% endif %}
|
||||
<tr><td class="fixwidth"> </td><td><i>No information submitted</i></td></tr>
|
||||
{% endif %}
|
||||
|
||||
{% if ipr.unbound_form or ipr.lic_checkbox %}
|
||||
{% if ipr.lic_checkbox %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% if ipr.unbound_form %} {{ ipr.lic_checkbox }} {% endif %}
|
||||
The individual submitting this template represents and warrants that all
|
||||
terms and conditions that must be satisfied for implementers of any
|
||||
covered IETF specification to obtain a license have been disclosed in this
|
||||
|
@ -330,6 +308,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<b><i>Note: The individual submitting this template represents and warrants
|
||||
|
@ -352,7 +331,8 @@
|
|||
IETF Participant in Section III above)
|
||||
</th>
|
||||
</tr>
|
||||
{% if ipr.unbound_form or ipr.submitter.name %}
|
||||
{% block section7_data %}
|
||||
{% if ipr.submitter.name %}
|
||||
<tr><td class="fixwidth">Name:</td> <td><b>{{ ipr.submitter.name }}</b></td></tr>
|
||||
<tr><td class="fixwidth">Title:</td> <td><b>{{ ipr.submitter.title }}</b></td></tr>
|
||||
<tr><td class="fixwidth">Department:</td> <td><b>{{ ipr.submitter.department }}</b></td></tr>
|
||||
|
@ -364,6 +344,7 @@
|
|||
{% else %}
|
||||
<tr><td colspan="2"><i>No information submitted</td></tr>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</table>
|
||||
</blockquote>
|
||||
{% endblock %}
|
||||
|
@ -378,19 +359,20 @@
|
|||
Other Notes:
|
||||
</th>
|
||||
</tr>
|
||||
{% if ipr.unbound_form %}
|
||||
<tr><td class="fixwidth"> </td><td><b>{{ ipr.other_notes }}</b></td></tr>
|
||||
{% else %}
|
||||
{% block section8_data %}
|
||||
{% if ipr.other_notes %}
|
||||
<tr><td> </td><td><b>{{ ipr.other_notes|escape|linebreaks }}</b></td></tr>
|
||||
{% else %}
|
||||
<tr><td colspan="2"><i>No information submitted</i></td></tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</table>
|
||||
</blockquote>
|
||||
{% endblock %}
|
||||
|
||||
{% endif %}
|
||||
{{ debug }}
|
||||
|
||||
{% block bot_info %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<h3>Archives by Year</h3>
|
||||
<ul>
|
||||
{% for year in date_list %}
|
||||
<li><a href="{{ year|date:"Y" }}/">{{ year|date:"Y" }}</a>
|
||||
<li><a href="/ipr/{{ year|date:"Y" }}/">{{ year|date:"Y" }}</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -53,4 +53,18 @@
|
|||
</p>
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
<form>
|
||||
{% endblock %}
|
||||
|
||||
{% block section1_data %}{{ form.section1 }}{% endblock %}
|
||||
{% block section2_data %}{{ form.section2 }}{% endblock %}
|
||||
{% block section3_data %}{{ form.section3 }}{% endblock %}
|
||||
{% block section4_data %}{{ form.section4 }}{% endblock %}
|
||||
{% block section5_data %}{{ form.section5 }}{% endblock %}
|
||||
{% block section6_data %}{{ form.section6 }}{% endblock %}
|
||||
{% block section7_data %}{{ form.section7 }}{% endblock %}
|
||||
{% block section8_data %}{{ form.section8 }}{% endblock %}
|
||||
{% block bot_info %}
|
||||
<center><input type="submit" name="submit" value="Submit"></center>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -131,3 +131,48 @@ def flattenl(list):
|
|||
[ 'a', 'b', 'c', 'd' ]
|
||||
"""
|
||||
return reduce(operator.__concat__, list)
|
||||
|
||||
|
||||
def split_form(html, blocks):
|
||||
"""Split the rendering of a form into a dictionary of named blocks.
|
||||
|
||||
Takes the html of the rendered form as the first argument.
|
||||
|
||||
Expects a dictionary as the second argument, with desired block
|
||||
name and a field specification as key:value pairs.
|
||||
|
||||
The field specification can be either a list of field names, or
|
||||
a string with the field names separated by whitespace.
|
||||
|
||||
The return value is a new dictionary, with the same keys as the
|
||||
block specification dictionary, and the form rendering matching
|
||||
the specified keys as the value.
|
||||
|
||||
Any line in the rendered form which doesn't match any block's
|
||||
field list will cause an exception to be raised.
|
||||
"""
|
||||
import re
|
||||
output = dict([(block,[]) for block in blocks])
|
||||
# handle field lists in string form
|
||||
for block in blocks:
|
||||
if type(blocks[block]) == type(""):
|
||||
blocks[block] = blocks[block].split()
|
||||
|
||||
# collapse radio button html to one line
|
||||
html = re.sub('\n(.*type="radio".*\n)', "\g<1>", html)
|
||||
html = re.sub('(?m)^(.*type="radio".*)\n', "\g<1>", html)
|
||||
|
||||
for line in html.split('\n'):
|
||||
found = False
|
||||
for block in blocks:
|
||||
for field in blocks[block]:
|
||||
if ('name="%s"' % field) in line:
|
||||
output[block].append(line)
|
||||
found = True
|
||||
if not found:
|
||||
raise LookupError("Could not place line in any section: '%s'" % line)
|
||||
|
||||
for block in output:
|
||||
output[block] = "\n".join(output[block])
|
||||
|
||||
return output
|
||||
|
|
Loading…
Reference in a new issue