Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F67826725
forms.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
Mon, Jun 24, 14:01
Size
11 KB
Mime Type
text/x-python
Expires
Wed, Jun 26, 14:01 (2 d)
Engine
blob
Format
Raw Data
Handle
18477628
Attached To
R3600 invenio-infoscience
forms.py
View Options
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2012, 2013, 2014, 2015 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.
"""Extended WTForms field.
Classes TimeField, DatePickerWidget, DateTimePickerWidget and TimePickerWidget
are taken from `flask-admin` extension.
:copyright: (c) 2011 by wilsaj.
:license: BSD, see LICENSE for more details.
:source: https://raw.github.com/wilsaj/flask-admin/master/flask_admin/wtforms.py
"""
import
datetime
import
time
from
flask
import
current_app
,
session
from
flask_wtf
import
Form
from
wtforms.compat
import
text_type
from
wtforms.ext.csrf.session
import
SessionSecureForm
from
wtforms.fields
import
Field
,
FileField
,
HiddenField
,
StringField
from
wtforms.form
import
Form
as
WTForm
from
wtforms.widgets
import
HTMLString
,
TextInput
,
html_params
class
RowWidget
(
object
):
"""Renders a list of fields as a set of table rows with th/td pairs."""
def
__init__
(
self
,
**
kwargs
):
"""Init class."""
self
.
defaults
=
kwargs
def
__call__
(
self
,
field
,
class_
=
''
,
row_class
=
'row'
,
**
kwargs
):
"""There are Bootstrap 3 specific improvements for row wrapping."""
html
=
[]
hidden
=
''
arguments
=
self
.
defaults
arguments
.
update
(
kwargs
)
classes
=
arguments
.
get
(
'classes'
,
{})
for
i
,
subfield
in
enumerate
(
field
):
if
subfield
.
type
==
'HiddenField'
:
hidden
+=
text_type
(
subfield
)
else
:
wrapper_class
=
classes
.
get
(
i
,
''
)
html
.
append
(
'
%s
<div class="
%s
">
%s
</div>'
%
(
hidden
,
wrapper_class
,
text_type
(
subfield
(
class_
=
class_
,
placeholder
=
subfield
.
label
.
text
))))
hidden
=
''
if
hidden
:
html
.
append
(
hidden
)
return
HTMLString
(
'<div class="
%s
">'
%
(
row_class
,
)
+
''
.
join
(
html
)
+
'</div>'
)
class
TimeField
(
Field
):
"""A text field which stores a `time.time` matching a format."""
widget
=
TextInput
()
def
__init__
(
self
,
label
=
None
,
validators
=
None
,
format
=
'%H:%M:%S'
,
**
kwargs
):
"""Init."""
super
(
TimeField
,
self
)
.
__init__
(
label
,
validators
,
**
kwargs
)
self
.
format
=
format
def
_value
(
self
):
if
self
.
raw_data
:
return
u' '
.
join
(
self
.
raw_data
)
else
:
return
self
.
data
and
self
.
data
.
strftime
(
self
.
format
)
or
u''
def
process_formdata
(
self
,
valuelist
):
"""Join time string."""
if
valuelist
:
time_str
=
u' '
.
join
(
valuelist
)
try
:
timetuple
=
time
.
strptime
(
time_str
,
self
.
format
)
self
.
data
=
datetime
.
time
(
*
timetuple
[
3
:
6
])
except
ValueError
:
self
.
data
=
None
raise
class
DatePickerWidget
(
TextInput
):
"""
TextInput widget that adds a 'datepicker' class.
TextInput widget that adds a 'datepicker' class to the html input
element; this makes it easy to write a jQuery selector that adds a
UI widget for date picking.
"""
def
__call__
(
self
,
field
,
**
kwargs
):
"""Call."""
c
=
kwargs
.
pop
(
'class'
,
''
)
or
kwargs
.
pop
(
'class_'
,
''
)
kwargs
[
'class'
]
=
u'datepicker
%s
'
%
c
return
super
(
DatePickerWidget
,
self
)
.
__call__
(
field
,
**
kwargs
)
class
DateTimePickerWidget
(
TextInput
):
"""
TextInput widget that adds a 'datetimepicker' class.
TextInput widget that adds a 'datetimepicker' class to the html
adds a UI widget for datetime picking.
"""
def
__call__
(
self
,
field
,
**
kwargs
):
"""Add class datepicker."""
c
=
kwargs
.
pop
(
'class'
,
''
)
or
kwargs
.
pop
(
'class_'
,
''
)
kwargs
[
'class'
]
=
u'datetimepicker
%s
'
%
c
return
super
(
DateTimePickerWidget
,
self
)
.
__call__
(
field
,
**
kwargs
)
class
TimePickerWidget
(
TextInput
):
"""
TextInput widget that adds a 'timepicker' class.
TextInput widget that adds a 'timepicker' class to the html
input element; this makes it easy to write a jQuery selector that
adds a UI widget for time picking.
"""
def
__call__
(
self
,
field
,
**
kwargs
):
"""Add class timepicker."""
c
=
kwargs
.
pop
(
'class'
,
''
)
or
kwargs
.
pop
(
'class_'
,
''
)
kwargs
[
'class'
]
=
u'timepicker
%s
'
%
c
return
super
(
TimePickerWidget
,
self
)
.
__call__
(
field
,
**
kwargs
)
class
AutocompleteField
(
StringField
):
"""Text field with simple autocompletion."""
def
__init__
(
self
,
label
=
None
,
validators
=
None
,
data_provide
=
"typeahead"
,
data_source
=
None
,
**
kwargs
):
"""Init."""
super
(
AutocompleteField
,
self
)
.
__init__
(
label
,
validators
,
**
kwargs
)
if
data_source
:
self
.
widget
=
TypeheadWidget
(
data_source
,
data_provide
)
class
TypeheadWidget
(
object
):
"""TextInput that use typeahead for autocompletion."""
def
__init__
(
self
,
autocomplete_list
,
data_provide
):
"""Init autocompletion."""
if
callable
(
autocomplete_list
):
self
.
autocomplete_list
=
autocomplete_list
()
else
:
self
.
autocomplete_list
=
'["{}"]'
.
format
(
'","'
.
join
(
autocomplete_list
))
self
.
data_provide
=
data_provide
def
__call__
(
self
,
field
,
**
kwargs
):
"""Define special attributes."""
kwargs
.
setdefault
(
'id'
,
field
.
id
)
kwargs
.
setdefault
(
'type'
,
'text'
)
kwargs
.
setdefault
(
'data-provide'
,
self
.
data_provide
)
kwargs
.
setdefault
(
'data-source'
,
self
.
autocomplete_list
)
if
'value'
not
in
kwargs
:
kwargs
[
'value'
]
=
field
.
_value
()
return
HTMLString
(
u'<input
%s
/>'
%
html_params
(
name
=
field
.
name
,
**
kwargs
))
class
RemoteAutocompleteField
(
StringField
):
"""Define a text field with autocompletion from remote.
How to use it:
First, use RemoteAutocompleteField in a form.
.. code-block:: python
class MyForm(InvenioBaseForm):
myfield = RemoteAutocompleteField(
'My Label',
# remote url where the field can ask suggestions
remote='/api/path/to/query?query=%QUERY',
# minimum length to start query
min_length=3,
# highlight the results in suggestions
highlight='true',
# field to use as key to submit with the form
data_key='field_to_use_as_key',
# field to visualize in the input field
data_value='field_to_visualize'
)
Then, create the API function that returns suggestions from
url path `/api/path/to/query`.
Note: you should return the results in JSON format, like:
.. code-block:: javascript
{
"results": [
{
field_to_use_as_key: 'my_key_1',
field_to_visualize: 'my_label_1'
},
{
field_to_use_as_key: 'my_key_2',
field_to_visualize: 'my_label_2'
},
]
}
After that, you should manually initialize the javascript.
To do that, for example, you can create a javascript init
file `init.js` into your module's directory.
E.g: `invenio/modules/mymodule/static/js/mymodule/init.js`:
.. code-block:: javascript
require([
'js/remote.autocomplete.field'
], function(autocomplete) {
// init the javascript interface
autocomplete.attachTo($('input.remote-typeahead-widget'))
})
Finally, if you create a new `init.js` file, you need to
add this in your bundle in your `bundles.py` file.
E.g:
.. code-block:: python
js = Bundle(
'js/mymodule/init.js',
filters=RequireJSFilter(exclude=[_j, _i]),
output="mymodule-init.js",
weight=50
)
"""
def
__init__
(
self
,
label
=
None
,
validators
=
None
,
remote
=
None
,
min_length
=
None
,
highlight
=
None
,
data_key
=
None
,
data_value
=
None
,
*
args
,
**
kwargs
):
"""Init class."""
super
(
RemoteAutocompleteField
,
self
)
.
__init__
(
label
,
validators
,
*
args
,
**
kwargs
)
self
.
kwargs
=
{}
self
.
kwargs
[
'data-remoteautocomplete-remote'
]
=
remote
or
''
self
.
kwargs
[
'data-remoteautocomplete-minLength'
]
=
min_length
or
3
self
.
kwargs
[
'data-remoteautocomplete-highlight'
]
=
highlight
or
'true'
self
.
kwargs
[
'data-remoteautocomplete-data-key'
]
=
data_key
or
''
self
.
kwargs
[
'data-remoteautocomplete-data-value'
]
=
data_value
or
''
self
.
widget
=
RemoteTypeheadWidget
(
label
,
**
kwargs
)
def
set_remote
(
self
,
value
):
"""Update remote url."""
self
.
widget
.
set_remote
(
value
)
class
RemoteTypeheadWidget
(
TextInput
):
"""Typeahead widget that acquire data from remote."""
def
__init__
(
self
,
label
,
**
kwargs
):
"""Init class."""
self
.
label
=
label
self
.
kwargs
=
{}
super
(
RemoteTypeheadWidget
,
self
)
.
__init__
()
def
__call__
(
self
,
field
,
**
kwargs
):
"""Configure the html field."""
kwargs
.
update
(
field
.
kwargs
)
kwargs
.
update
(
self
.
kwargs
)
kwargs
[
'class_'
]
=
kwargs
[
'class_'
]
+
' remote-typeahead-widget '
return
super
(
RemoteTypeheadWidget
,
self
)
.
__call__
(
field
,
**
kwargs
)
def
set_remote
(
self
,
value
):
"""Update remote url."""
self
.
kwargs
[
'data-remoteautocomplete-remote'
]
=
value
def
has_file_field
(
form
):
"""
Test whether or not a form has a FileField in it.
This is used to know whether or not we need to set enctype to
multipart/form-data.
"""
for
field
in
form
:
if
isinstance
(
field
,
FileField
):
return
True
return
False
class
FilterStringField
(
StringField
):
"""Define a FilterStringField."""
alias
=
None
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""Init."""
self
.
alias
=
kwargs
.
get
(
'alias'
)
if
'alias'
in
kwargs
:
del
kwargs
[
'alias'
]
super
(
FilterStringField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
if
not
self
.
raw_data
:
self
.
raw_data
=
[]
def
_value
(
self
):
if
self
.
raw_data
:
return
self
.
raw_data
.
pop
()
return
u''
class
InvenioForm
(
WTForm
):
"""Define a Invenio Form."""
@property
def
required_field_names
(
self
):
"""Return all required field names."""
return
[
field
.
name
for
field
in
self
if
hasattr
(
field
,
'required'
)]
class
InvenioBaseForm
(
Form
,
SessionSecureForm
):
"""Define a InvenioBaseForm."""
# SECRET_KEY = CFG_SITE_SECRET_KEY
TIME_LIMIT
=
1200.0
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""Init."""
super
(
InvenioBaseForm
,
self
)
.
__init__
(
*
args
,
csrf_context
=
session
,
**
kwargs
)
def
add_fields
(
self
,
name
,
field
):
"""Add a field."""
self
.
__setattr__
(
name
,
field
)
def
validate_csrf_token
(
self
,
field
):
"""Disable CRSF proection during testing."""
if
current_app
.
testing
:
return
super
(
InvenioBaseForm
,
self
)
.
validate_csrf_token
(
field
)
class
FilterForm
(
InvenioBaseForm
):
"""Filter forms contains hidden fields to keep sorting."""
sort_by
=
HiddenField
()
order
=
HiddenField
()
Event Timeline
Log In to Comment