Skip to content

Instantly share code, notes, and snippets.

@moschlar
Created November 12, 2014 11:09
Show Gist options
  • Save moschlar/c56c3382292f83b882da to your computer and use it in GitHub Desktop.
Save moschlar/c56c3382292f83b882da to your computer and use it in GitHub Desktop.
Minimal working example to demonstrate issue TurboGears/sprox#4
'''Minimal working example to demonstrate issue TurboGears/sprox#4
Summary:
If the "many" side of a sqlalchemy relationship is also a required field
in sprox, the MultipleSelectField gets a UnicodeString validator, which
simply converts the value to a string, regardless of its type (in this
example, it leads to the repr string being used as the value). For
determining the selected options of the select field, the in operator
is then used on whatever string got generated first, leading to awkwardly
wrong selected values.
'''
from sqlalchemy import Column, Integer, ForeignKey, create_engine
from sqlalchemy.orm import relationship, backref, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sprox.formbase import EditableForm
from sprox.widgets.tw2widgets.widgets import PropertyMultipleSelectField
#-----------------------------------------------------------------------------
# tw2 middleware mocking
import tw2.core.core
import tw2.core.middleware as tmw
_request_local = {'middleware': tmw.make_middleware(None)}
tw2.core.core.request_local = lambda: _request_local
from tw2.core.core import request_local
#-----------------------------------------------------------------------------
Base = declarative_base()
class Parent(Base):
__tablename__ = 'parents'
id = Column(Integer, primary_key=True)
class Child(Base):
__tablename__ = 'children'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey(Parent.id))
parent = relationship(Parent, backref=backref('children'))
def __repr__(self):
return '<Child(id=%r)>' % (self.id)
class MyPropertyMultipleSelectField(PropertyMultipleSelectField):
'''This subclass is just for "inspection" purposes'''
def prepare(self):
'''Note how self.value changes'''
print self.validator, self.value
result = super(MyPropertyMultipleSelectField, self).prepare()
print self.validator, self.value
return result
class EditParentForm(EditableForm):
__model__ = Parent
__require_fields__ = ['children']
__field_widget_types__ = {'children': MyPropertyMultipleSelectField}
if __name__ == '__main__':
engine = create_engine('sqlite:///:memory:', echo=False)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
parent = Parent()
session.add(parent)
children = [Child(id=1), Child(id=3), Child(id=5), Child(id=13, parent=parent)]
session.add_all(children)
session.commit()
value = session.query(Parent).first()
print [c.id for c in value.children]
edit_parent_form = EditParentForm(session)
widgets = edit_parent_form._do_get_field_widgets(['children'])
print widgets['children'], widgets['children'].validator
print edit_parent_form.display(value=value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment