Repository: flask-admin/flask-admin

Issue:
Float positions cut at 2 decimals
I'm using flask-admin in conjuction with sqla to handle views on my database. 

flask-admin : 1.3.0
wtforms: 2.0.2

When adding floating point values, like a latitude or a longitude, I use to have at least 4 decimals (down to 10m location quality). Inserting in the database is OK, viewing the data in "table" format is OK, but when clicking the "edit" link, the form opens with only 2 decimals.

I think this https://github.com/flask-admin/flask-admin/blob/master/flask_admin/contrib/sqla/form.py#L328 line is doing a lot of damages, since it seems sqla `Float` only accepts `decimal_return_scale` as arg now. 
Changing

``` python
places = getattr(column.type, 'scale', 2)
```

for

``` python
places = getattr(column.type, 'decimal_return_scale', 2)
```

solves the issue. 



Discussion:
These docs say `decimal_return_scales` is new in 0.9.0: http://docs.sqlalchemy.org/en/latest/core/type_basics.html#sqlalchemy.types.Float.params.decimal_return_scale

So we probably would need to make it fail over to using `scale` for backwards compatibilty.

Can you submit the pull request?

Actually, looking at their documentation, it seems that the default value is 10 for `scale`, but in flask-admin & wtforms, it's 2.

On the other hand, if the "default value" is 10, why does `getattr(column.type, 'scale')` return `None` ? I don't get it...

I can make a PR for sure, but I'm not completely sure how you see the deprecation route here ?


Resolving patch:
diff --git a/flask_admin/contrib/sqla/form.py b/flask_admin/contrib/sqla/form.py
--- a/flask_admin/contrib/sqla/form.py
+++ b/flask_admin/contrib/sqla/form.py
@@ -270,7 +270,7 @@ def _string_common(cls, column, field_args, **extra):
         if column.type.length:
             field_args['validators'].append(validators.Length(max=column.type.length))
 
-    @converts('String', 'Unicode')
+    @converts('String')  # includes VARCHAR, CHAR, and Unicode
     def conv_String(self, column, field_args, **extra):
         if hasattr(column.type, 'enums'):
             accepted_values = list(column.type.enums)
@@ -293,8 +293,7 @@ def conv_String(self, column, field_args, **extra):
         self._string_common(column=column, field_args=field_args, **extra)
         return fields.StringField(**field_args)
 
-    @converts('Text', 'UnicodeText',
-              'sqlalchemy.types.LargeBinary', 'sqlalchemy.types.Binary')
+    @converts('Text', 'LargeBinary', 'Binary')  # includes UnicodeText
     def conv_Text(self, field_args, **extra):
         self._string_common(field_args=field_args, **extra)
         return fields.TextAreaField(**field_args)
@@ -308,7 +307,7 @@ def convert_date(self, field_args, **extra):
         field_args['widget'] = form.DatePickerWidget()
         return fields.DateField(**field_args)
 
-    @converts('DateTime')
+    @converts('DateTime')  # includes TIMESTAMP
     def convert_datetime(self, field_args, **extra):
         return form.DateTimeField(**field_args)
 
@@ -316,40 +315,32 @@ def convert_datetime(self, field_args, **extra):
     def convert_time(self, field_args, **extra):
         return form.TimeField(**field_args)
 
-    @converts('Integer', 'SmallInteger')
+    @converts('Integer')  # includes BigInteger and SmallInteger
     def handle_integer_types(self, column, field_args, **extra):
         unsigned = getattr(column.type, 'unsigned', False)
         if unsigned:
             field_args['validators'].append(validators.NumberRange(min=0))
         return fields.IntegerField(**field_args)
 
-    @converts('Numeric', 'Float')
+    @converts('Numeric')  # includes DECIMAL, Float/FLOAT, REAL, and DOUBLE
     def handle_decimal_types(self, column, field_args, **extra):
-        places = getattr(column.type, 'scale', 2)
-        if places is not None:
-            field_args['places'] = places
+        # override default decimal places limit, use database defaults instead
+        field_args.setdefault('places', None)
         return fields.DecimalField(**field_args)
 
-    @converts('databases.mysql.MSYear')
-    def conv_MSYear(self, field_args, **extra):
-        field_args['validators'].append(validators.NumberRange(min=1901, max=2155))
-        return fields.StringField(**field_args)
-
-    @converts('sqlalchemy.dialects.postgresql.base.INET',
-              'databases.postgres.PGInet', 'dialects.postgresql.base.INET')
+    @converts('sqlalchemy.dialects.postgresql.base.INET')
     def conv_PGInet(self, field_args, **extra):
         field_args.setdefault('label', u'IP Address')
         field_args['validators'].append(validators.IPAddress())
         return fields.StringField(**field_args)
 
-    @converts('sqlalchemy.dialects.postgresql.base.MACADDR',
-              'dialects.postgresql.base.MACADDR')
+    @converts('sqlalchemy.dialects.postgresql.base.MACADDR')
     def conv_PGMacaddr(self, field_args, **extra):
         field_args.setdefault('label', u'MAC Address')
         field_args['validators'].append(validators.MacAddress())
         return fields.StringField(**field_args)
 
-    @converts('dialects.postgresql.base.UUID')
+    @converts('sqlalchemy.dialects.postgresql.base.UUID')
     def conv_PGUuid(self, field_args, **extra):
         field_args.setdefault('label', u'UUID')
         field_args['validators'].append(validators.UUID())


Test patch: