# along with this program. If not, see <http://www.gnu.org/licenses/>.
import wtforms
+from jsonschema import Draft4Validator
from mediagoblin.tools.text import tag_length_validator
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
from mediagoblin.tools.licenses import licenses_as_choices
+from mediagoblin.tools.metadata import DEFAULT_SCHEMA, DEFAULT_CHECKER
from mediagoblin.auth.tools import normalize_user_or_email_field
description=_(
"Enter your password to prove you own this account."))
+class MetaDataValidator(object):
+ """
+ Custom validator which runs form data in a MetaDataForm through a jsonschema
+ validator and passes errors recieved in jsonschema to wtforms.
+
+ :param schema The json schema to validate the data against. By
+ default this uses the DEFAULT_SCHEMA from
+ mediagoblin.tools.metadata.
+ :param format_checker The FormatChecker object that limits which types
+ jsonschema can recognize. By default this uses
+ DEFAULT_CHECKER from mediagoblin.tools.metadata.
+ """
+ def __init__(self, schema=DEFAULT_SCHEMA, format_checker=DEFAULT_CHECKER):
+ self.schema = schema
+ self.format_checker = format_checker
+
+ def __call__(self, form, field):
+ metadata_dict = {field.data:form.value.data}
+ validator = Draft4Validator(self.schema,
+ format_checker=self.format_checker)
+ errors = [e.message
+ for e in validator.iter_errors(metadata_dict)]
+ if len(errors) >= 1:
+ raise wtforms.validators.ValidationError(
+ errors.pop())
+
class MetaDataForm(wtforms.Form):
- identifier = wtforms.TextField(_(u'Identifier'))
+ identifier = wtforms.TextField(_(u'Identifier'),[MetaDataValidator()])
value = wtforms.TextField(_(u'Value'))
class EditMetaDataForm(wtforms.Form):
media_metadata = wtforms.FieldList(
- wtforms.FormField(MetaDataForm, label="")
+ wtforms.FormField(MetaDataForm, ""),
)
from pyld import jsonld
from werkzeug.exceptions import Forbidden
from werkzeug.utils import secure_filename
+from jsonschema import ValidationError, Draft4Validator
from mediagoblin import messages
from mediagoblin import mg_globals
get_user_collection, user_has_privilege,
user_not_banned)
from mediagoblin.tools.crypto import get_timed_signer_url
-from mediagoblin.tools.metadata import compact_and_validate
+from mediagoblin.tools.metadata import (compact_and_validate, DEFAULT_CHECKER,
+ DEFAULT_SCHEMA)
from mediagoblin.tools.mail import email_debug_message
from mediagoblin.tools.response import (render_to_response,
redirect, redirect_obj, render_404)
if request.method == "POST" and form.validate():
metadata_dict = dict([(row['identifier'],row['value'])
for row in form.media_metadata.data])
+ json_ld_metadata = None
json_ld_metadata = compact_and_validate(metadata_dict)
media.media_metadata = json_ld_metadata
media.save()
return redirect_obj(request, media)
- if media.media_metadata:
+ if media.media_metadata and len(form.media_metadata) == 0:
for identifier, value in media.media_metadata.iteritems():
if identifier == "@context": continue
form.media_metadata.append_entry({
'identifier':identifier,
'value':value})
- else:
- form.media_metadata.append_entry({
- 'identifier':"",
- 'value':""})
- form.media_metadata.append_entry({
- 'identifier':"",
- 'value':""})
+
return render_to_response(
request,
'mediagoblin/edit/metadata.html',
/* for the media metadata editing table */
table.metadata_editor {
-
margin: 10px auto;
- width: 1000px;
-}
-
-table.metadata_editor tr th {
- width:100px;
+ width: 800px;
}
table.metadata_editor tr td {
- width:300px;
+ width:350px;
}
table.metadata_editor tr td.form_field_input input {
- width:300px;
+ width:350px;
}
<form action="" method="POST" id="metadata_form">
<!-- This table holds all the information about the media entry's metadata -->
- <h3>{% trans %}Data{% endtrans %}</h3>
+ <h3>{% trans %}MetaData{% endtrans %}</h3>
<table class="metadata_editor" id="metadata_list" >
{{ wtforms_util.render_fieldlist_as_table_rows(form.media_metadata) }}
</table>
<!-- These are the buttons you use to control the form -->
<table class="metadata_editor" id="buttons_bottom">
<tr>
- <th></th>
<td><input type=button value="{% trans %}Add new Row{% endtrans %}"
class="button_action" id="add_new_metadata_row" />
</td>
- <th></th>
<td><input type=submit value="{% trans %}Update Metadata{% endtrans %}"
class="button_action_highlight" /></td>
</tr>
<tr>
- <th></th>
<td><input type=button value="{% trans %}Clear empty Rows{% endtrans %}"
class="button_action" id="clear_empty_rows" /></td>
</tr>
{% macro render_form_as_table_row(form) %}
<tr>
{%- for field in form %}
- <th>{{ render_label_p(field) }}</th>
<td class="form_field_input">
{{field}}
- {%- if field.errors -%}
- <br />
- <ul class="errors">
- {% for error in field.errors %}
- <li>{{error}}</li>
- {%- endfor %}
- </ul>
- {%- endif -%}
</td>
{%- endfor %}
</tr>
+ <tr>
+ {%- for field in form %}
+ {% for error in field.errors %}
+ <tr>
+ <td>
+ <p class="form_field_error">{{error}}</p>
+ </td>
+ </tr>
+ {%- endfor %}
+ {%- endfor %}
{%- endmacro %}
{% macro render_field_as_table_row(field) %}
<th>{{ field.label.text }}</th>
<td>
{{field}}
- {% if field.errors %}
- <br />
- <ul class="errors">
- {% for error in field.errors %}
- <li>{{error}}</li>
- {% endfor %}
- </ul>
- {% endif %}
</td>
</tr>
+ {% for error in field.errors %}
+ <tr>
+ <td>
+ <p class="form_field_error">{{error}}</p>
+ </td>
+ </tr>
+ {%- endfor %}
{% endmacro %}
{% macro render_fieldlist_as_table_rows(fieldlist) %}