import datetime as dt
from collections import OrderedDict
from . import (FieldSource, from_bool, from_int, from_float, from_str,
from_date, from_time, from_datetime)
from ..fields import SelectField
__author__ = 'Juan Manuel Bermúdez Cabrera'
[docs]class SQLAlchemySource(FieldSource):
"""Field source for SQLAlchemy objects.
This field source supports classes and objects created using SQLAlchemy's
Declarative Mapping system as well as SQLAlchemy's Table objects. This means
that fields generated by the following code snippets are the same::
import os
import sys
os.environ['QT_API'] = 'pyqt4'
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
import campos
engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
last = Column(String)
password = Column(String)
app = QApplication(sys.argv)
# using an object
user = User(id=1, name='Rajesh', last='Koothrappali', password='ok')
source = campos.get_fields_source(user)
fields1 = source.fields
# using a declarative class
source = campos.get_fields_source(User)
fields2 = source.fields
# using a Table object
source = campos.get_fields_source(User.__table__)
fields3 = source.fields
"""
def get_members(self):
table = getattr(self.object, '__table__', self.object)
columns = table.columns
members = []
for column in columns:
members.append((column.name, column))
return members
def create_fields(self, attributes):
from sqlalchemy import (Boolean, Integer, Float, String, Text, Date,
Enum, Time, DateTime)
# exclude attributes with unsupported values
filtered = OrderedDict()
for attr, text_column in attributes.items():
text, column = text_column
if column.type.python_type in self.SUPPORTED_TYPES:
filtered[attr] = text, column
fields = OrderedDict()
for attr, text_column in filtered.items():
text, column = text_column
ctype = column.type
ctype_class = type(ctype)
field = None
if ctype_class == Boolean:
field = from_bool(attr, text, False)
elif ctype_class == Integer:
field = from_int(attr, text, 0)
elif ctype_class == Float:
kwargs = {}
if ctype.precision is not None:
kwargs['precision'] = ctype.precision
field = from_float(attr, text, 0, **kwargs)
elif ctype_class == String:
kwargs = {}
if ctype.length is not None:
kwargs['max_length'] = ctype.length
field = from_str(attr, text, '', **kwargs)
elif ctype_class == Text:
kwargs = {}
if ctype.length is not None:
kwargs['max_length'] = ctype.length
field = from_str(attr, text, '', istext=True, **kwargs)
elif ctype_class == Date:
field = from_date(attr, text, dt.date.today())
elif ctype_class == Time:
field = from_time(attr, text, dt.time.min)
elif ctype_class == DateTime:
field = from_datetime(attr, text, dt.datetime.now())
elif ctype_class == Enum:
field = SelectField(name=attr, text=text, choices=ctype.enums)
if field is not None:
fields[field.name] = field
return fields