Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F98275019
field_base.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Jan 11, 16:47
Size
9 KB
Mime Type
text/x-python
Expires
Mon, Jan 13, 16:47 (2 d)
Engine
blob
Format
Raw Data
Handle
23547954
Attached To
R3600 invenio-infoscience
field_base.py
View Options
# -*- coding: utf-8 -*-
##
## This file is part of Invenio.
## Copyright (C) 2013, 2014 CERN.
##
## Invenio is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of the
## License, or (at your option) any later version.
##
## Invenio is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Invenio; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
"""
Implementation of validators, post-processors and auto-complete functions.
Validators
----------
Following is a short overview over how validators may be defined for fields.
Inline validators (always executed)::
class MyForm(...):
myfield = MyField()
def validate_myfield(form, field):
raise ValidationError("Message")
External validators (always executed)::
def my_validator(form, field):
raise ValidationError("Message")
class MyForm(...):
myfield = MyField(validators=[my_validator])
Field defined validators (always executed)::
class MyField(...):
# ...
def pre_validate(self, form):
raise ValidationError("Message")
Default field validators (executed only if external validators are not
defined)::
class MyField(...):
def __init__(self, **kwargs):
defaults = dict(validators=[my_validator])
defaults.update(kwargs)
super(MyField, self).__init__(**defaults)
See http://wtforms.simplecodes.com/docs/1.0.4/validators.html for how to
write validators.
Post-processors
---------------
Post processors follows the same pattern as validators. You may thus specify:
- Inline processors:::
Form.post_process_<field>(form, field)
- External processors:::
def my_processor(form, field):
...
myfield = MyField(processors=[my_processor])
- Field defined processors (please method documentation):::
Field.post_process(self, form, extra_processors=[])
Auto-complete
-------------
- External auto-completion function:::
def my_autocomplete(form, field, limit=50):
...
myfield = MyField(autocomplete=my_autocomplete)
- Field defined auto-completion function (please method documentation):::
Field.autocomplete(self, form, limit=50)
"""
from
wtforms
import
Field
from
.form
import
CFG_FIELD_FLAGS
__all__
=
(
'WebDepositField'
,
)
class
WebDepositField
(
Field
):
"""Base field that all webdeposit fields must inherit from."""
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""
Initialize WebDeposit field.
Every field is associated with a marc field. To define this association
you have to specify the `export_key` for the recordext `Reader` or the
`cook_function` (for more complicated fields).
:param placeholder: str, Placeholder text for input fields.
:param icon: Name of icon (rendering of the icon is done by templates)
:type icon: str
:param autocomplete: callable, A function to auto-complete values
for field.
:param processors: list of callables, List of processors to run
for field.
:param validators: list of callables, List of WTForm validators.
If no validators are provided, validators defined
in webdeposit_config will be loaded.
:param hidden: Set to true to hide field. Default: False
:type hidden: bool
:param disabled: Set to true to disable field. Default: False
:type disabled: bool
:param export_key: Name of key to use during export
:type export_key: str or callable
:see http://wtforms.simplecodes.com/docs/1.0.4/validators.html for
how to write validators.
:see http://wtforms.simplecodes.com/docs/1.0.4/fields.html for further
keyword argument that can be provided on field initialization.
"""
# Pop WebDeposit specific kwargs before calling super()
self
.
placeholder
=
kwargs
.
pop
(
'placeholder'
,
None
)
self
.
group
=
kwargs
.
pop
(
'group'
,
None
)
self
.
icon
=
kwargs
.
pop
(
'icon'
,
None
)
self
.
autocomplete
=
kwargs
.
pop
(
'autocomplete'
,
None
)
self
.
processors
=
kwargs
.
pop
(
'processors'
,
None
)
self
.
export_key
=
kwargs
.
pop
(
'export_key'
,
None
)
self
.
widget_classes
=
kwargs
.
pop
(
'widget_classes'
,
None
)
self
.
autocomplete_limit
=
kwargs
.
pop
(
'autocomplete_limit'
,
20
)
# Initialize empty message variables, which are usually modified
# during the post-processing phases.
self
.
_messages
=
[]
self
.
_message_state
=
''
# Get flag values (e.g. hidden, disabled) before super() call.
# See CFG_FIELD_FLAGS for all defined flags.
flag_values
=
{}
for
flag
in
CFG_FIELD_FLAGS
:
flag_values
[
flag
]
=
kwargs
.
pop
(
flag
,
False
)
# Call super-constructor.
super
(
WebDepositField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
# Set flag values after super() call to ensure, flags set during
# super() are overwritten.
for
flag
,
value
in
flag_values
.
items
():
if
value
:
setattr
(
self
.
flags
,
flag
,
True
)
def
__call__
(
self
,
*
args
,
**
kwargs
):
"""Set custom keyword arguments when rendering field."""
if
'placeholder'
not
in
kwargs
and
self
.
placeholder
:
kwargs
[
'placeholder'
]
=
self
.
placeholder
if
'disabled'
not
in
kwargs
and
self
.
flags
.
disabled
:
kwargs
[
'disabled'
]
=
"disabled"
if
'class_'
in
kwargs
and
self
.
widget_classes
:
kwargs
[
'class_'
]
=
kwargs
[
'class_'
]
+
self
.
widget_classes
elif
self
.
widget_classes
:
kwargs
[
'class_'
]
=
self
.
widget_classes
if
self
.
autocomplete
:
kwargs
[
'data-autocomplete'
]
=
"1"
kwargs
[
'data-autocomplete-limit'
]
=
self
.
autocomplete_limit
return
super
(
WebDepositField
,
self
)
.
__call__
(
*
args
,
**
kwargs
)
def
reset_field_data
(
self
,
exclude
=
[]):
"""Reset the ``fields.data`` value to that of ``field.object_data``.
Usually not called directly, but rather through Form.reset_field_data()
:param exclude: List of formfield names to exclude.
"""
if
self
.
name
not
in
exclude
:
self
.
data
=
self
.
object_data
def
post_process
(
self
,
form
=
None
,
formfields
=
[],
extra_processors
=
[],
submit
=
False
):
"""Post process form before saving.
Usually you can do some of the following tasks in the post
processing:
* Set field flags (e.g. self.flags.hidden = True or
form.<field>.flags.hidden = True).
* Set messages (e.g. self.messages.append('text') and
self.message_state = 'info').
* Set values of other fields (e.g. form.<field>.data = '').
Processors may stop the processing chain by raising StopIteration.
IMPORTANT: By default the method will execute custom post processors
defined in the webdeposit_config. If you override the method, be
sure to call this method to ensure extra processors are called::
super(MyField, self).post_process(
form, extra_processors=extra_processors
)
"""
# Check if post processing should run for this field
if
self
.
name
in
formfields
or
not
formfields
:
stop
=
False
for
p
in
(
self
.
processors
or
[]):
try
:
p
(
form
,
self
,
submit
=
submit
,
fields
=
formfields
)
except
StopIteration
:
stop
=
True
break
if
not
stop
:
for
p
in
(
extra_processors
or
[]):
p
(
form
,
self
,
submit
=
submit
,
fields
=
formfields
)
def
perform_autocomplete
(
self
,
form
,
name
,
term
,
limit
=
50
):
"""Run auto-complete method for field.
This method should not be called directly, instead use
Form.autocomplete().
"""
if
name
==
self
.
name
and
self
.
autocomplete
:
return
self
.
autocomplete
(
form
,
self
,
term
,
limit
=
limit
)
return
None
def
add_message
(
self
,
msg
,
state
=
None
):
"""Add a message.
:param msg: The message to set
:param state: State of message; info, warning, error, success.
"""
self
.
_messages
.
append
(
msg
)
if
state
:
self
.
_message_state
=
state
def
set_flags
(
self
,
flags
):
"""Set field flags."""
field_flags
=
flags
.
get
(
self
.
name
,
[])
for
check_flag
in
CFG_FIELD_FLAGS
:
setattr
(
self
.
flags
,
check_flag
,
check_flag
in
field_flags
)
@property
def
messages
(
self
):
"""Retrieve field messages."""
if
self
.
errors
:
return
{
self
.
name
:
dict
(
state
=
'error'
,
messages
=
self
.
errors
)}
else
:
return
{
self
.
name
:
dict
(
state
=
getattr
(
self
,
'_message_state'
,
''
),
messages
=
self
.
_messages
)}
Event Timeline
Log In to Comment