forms: make csv import parse dates accepts a list of columns (#4639)

Instead of a boolean which has way less chances to work. While
at it add a proper label for the "con" field.

Fixes #4637
This commit is contained in:
Riccardo Magliocchetti 2018-03-23 22:16:02 +01:00 committed by Grace Guo
parent f11cde9eb8
commit 76394d3f8f
3 changed files with 61 additions and 4 deletions

View File

@ -10,7 +10,7 @@ from flask_appbuilder.forms import DynamicForm
from flask_babel import lazy_gettext as _ from flask_babel import lazy_gettext as _
from flask_wtf.file import FileAllowed, FileField, FileRequired from flask_wtf.file import FileAllowed, FileField, FileRequired
from wtforms import ( from wtforms import (
BooleanField, IntegerField, SelectField, StringField) BooleanField, Field, IntegerField, SelectField, StringField)
from wtforms.ext.sqlalchemy.fields import QuerySelectField from wtforms.ext.sqlalchemy.fields import QuerySelectField
from wtforms.validators import DataRequired, NumberRange, Optional from wtforms.validators import DataRequired, NumberRange, Optional
@ -20,6 +20,32 @@ from superset.models import core as models
config = app.config config = app.config
class CommaSeparatedListField(Field):
widget = BS3TextFieldWidget()
def _value(self):
if self.data:
return u', '.join(self.data)
else:
return u''
def process_formdata(self, valuelist):
if valuelist:
self.data = [x.strip() for x in valuelist[0].split(',')]
else:
self.data = []
def filter_not_empty_values(value):
"""Returns a list of non empty values or None"""
if not value:
return None
data = [x for x in value if x]
if not data:
return None
return data
class CsvToDatabaseForm(DynamicForm): class CsvToDatabaseForm(DynamicForm):
# pylint: disable=E0211 # pylint: disable=E0211
def all_db_items(): def all_db_items():
@ -36,6 +62,7 @@ class CsvToDatabaseForm(DynamicForm):
validators=[ validators=[
FileRequired(), FileAllowed(['csv'], _('CSV Files Only!'))]) FileRequired(), FileAllowed(['csv'], _('CSV Files Only!'))])
con = QuerySelectField( con = QuerySelectField(
_('Database'),
query_factory=all_db_items, query_factory=all_db_items,
get_pk=lambda a: a.id, get_label=lambda a: a.database_name) get_pk=lambda a: a.id, get_label=lambda a: a.database_name)
sep = StringField( sep = StringField(
@ -99,9 +126,12 @@ class CsvToDatabaseForm(DynamicForm):
description=_( description=_(
'Skip blank lines rather than interpreting them ' 'Skip blank lines rather than interpreting them '
'as NaN values.')) 'as NaN values.'))
parse_dates = BooleanField( parse_dates = CommaSeparatedListField(
_('Parse Dates'), _('Parse Dates'),
description=_('Parse date values.')) description=_(
'A comma separated list of columns that should be '
'parsed as dates.'),
filters=[filter_not_empty_values])
infer_datetime_format = BooleanField( infer_datetime_format = BooleanField(
_('Infer Datetime Format'), _('Infer Datetime Format'),
description=_( description=_(

View File

@ -339,7 +339,6 @@ class CsvToDatabaseView(SimpleFormView):
form.mangle_dupe_cols.data = True form.mangle_dupe_cols.data = True
form.skipinitialspace.data = False form.skipinitialspace.data = False
form.skip_blank_lines.data = True form.skip_blank_lines.data = True
form.parse_dates.data = True
form.infer_datetime_format.data = True form.infer_datetime_format.data = True
form.decimal.data = '.' form.decimal.data = '.'
form.if_exists.data = 'append' form.if_exists.data = 'append'

28
tests/form_tests.py Normal file
View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from tests.base_tests import SupersetTestCase
from wtforms.form import Form
from superset.forms import (
CommaSeparatedListField, filter_not_empty_values)
class FormTestCase(SupersetTestCase):
def test_comma_separated_list_field(self):
field = CommaSeparatedListField().bind(Form(), 'foo')
field.process_formdata([u''])
self.assertEqual(field.data, [u''])
field.process_formdata(['a,comma,separated,list'])
self.assertEqual(field.data, [u'a', u'comma', u'separated', u'list'])
def test_filter_not_empty_values(self):
self.assertEqual(filter_not_empty_values(None), None)
self.assertEqual(filter_not_empty_values([]), None)
self.assertEqual(filter_not_empty_values(['']), None)
self.assertEqual(filter_not_empty_values(['hi']), ['hi'])