fix: remove session
param from some form schema, widget classes
this was originally used for injecting the test session, but i wound up using mock instead elsewhere, so this is just for consistency
This commit is contained in:
parent
a612bf3846
commit
a219f3e30d
4 changed files with 214 additions and 201 deletions
|
@ -155,9 +155,10 @@ class TestObjectRef(DataTestCase):
|
|||
self.session.commit()
|
||||
self.assertIsNotNone(person.uuid)
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
value = typ.deserialize(node, person.uuid)
|
||||
self.assertIs(value, person)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.ObjectRef(self.request)
|
||||
value = typ.deserialize(node, person.uuid)
|
||||
self.assertIs(value, person)
|
||||
|
||||
def test_dictify(self):
|
||||
model = self.app.model
|
||||
|
@ -181,42 +182,46 @@ class TestObjectRef(DataTestCase):
|
|||
value = typ.objectify(None)
|
||||
self.assertIsNone(value)
|
||||
|
||||
# model instance
|
||||
person = model.Person(full_name="Betty Boop")
|
||||
self.session.add(person)
|
||||
self.session.commit()
|
||||
self.assertIsNotNone(person.uuid)
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
|
||||
# can specify as uuid
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
value = typ.objectify(person.uuid)
|
||||
self.assertIs(value, person)
|
||||
# model instance
|
||||
person = model.Person(full_name="Betty Boop")
|
||||
self.session.add(person)
|
||||
self.session.commit()
|
||||
self.assertIsNotNone(person.uuid)
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
|
||||
# or can specify object proper
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
value = typ.objectify(person)
|
||||
self.assertIs(value, person)
|
||||
# can specify as uuid
|
||||
typ = mod.ObjectRef(self.request)
|
||||
value = typ.objectify(person.uuid)
|
||||
self.assertIs(value, person)
|
||||
|
||||
# error if not found
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
self.assertRaises(ValueError, typ.objectify, 'WRONG-UUID')
|
||||
# or can specify object proper
|
||||
typ = mod.ObjectRef(self.request)
|
||||
value = typ.objectify(person)
|
||||
self.assertIs(value, person)
|
||||
|
||||
# error if not found
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
typ = mod.ObjectRef(self.request)
|
||||
self.assertRaises(ValueError, typ.objectify, 'WRONG-UUID')
|
||||
|
||||
def test_get_query(self):
|
||||
model = self.app.model
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.ObjectRef(self.request)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
|
||||
def test_sort_query(self):
|
||||
model = self.app.model
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
query = typ.get_query()
|
||||
sorted_query = typ.sort_query(query)
|
||||
self.assertIs(sorted_query, query)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.ObjectRef(self.request)
|
||||
query = typ.get_query()
|
||||
sorted_query = typ.sort_query(query)
|
||||
self.assertIs(sorted_query, query)
|
||||
|
||||
def test_widget_maker(self):
|
||||
model = self.app.model
|
||||
|
@ -226,90 +231,98 @@ class TestObjectRef(DataTestCase):
|
|||
|
||||
# basic
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
widget = typ.widget_maker()
|
||||
self.assertEqual(len(widget.values), 1)
|
||||
self.assertEqual(widget.values[0][1], "Betty Boop")
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.ObjectRef(self.request)
|
||||
widget = typ.widget_maker()
|
||||
self.assertEqual(len(widget.values), 1)
|
||||
self.assertEqual(widget.values[0][1], "Betty Boop")
|
||||
|
||||
# empty option
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
typ = mod.ObjectRef(self.request, session=self.session, empty_option=True)
|
||||
widget = typ.widget_maker()
|
||||
self.assertEqual(len(widget.values), 2)
|
||||
self.assertEqual(widget.values[0][1], "(none)")
|
||||
self.assertEqual(widget.values[1][1], "Betty Boop")
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.ObjectRef(self.request, empty_option=True)
|
||||
widget = typ.widget_maker()
|
||||
self.assertEqual(len(widget.values), 2)
|
||||
self.assertEqual(widget.values[0][1], "(none)")
|
||||
self.assertEqual(widget.values[1][1], "Betty Boop")
|
||||
|
||||
|
||||
class TestPersonRef(WebTestCase):
|
||||
|
||||
def test_sort_query(self):
|
||||
typ = mod.PersonRef(self.request, session=self.session)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
sorted_query = typ.sort_query(query)
|
||||
self.assertIsInstance(sorted_query, orm.Query)
|
||||
self.assertIsNot(sorted_query, query)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.PersonRef(self.request)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
sorted_query = typ.sort_query(query)
|
||||
self.assertIsInstance(sorted_query, orm.Query)
|
||||
self.assertIsNot(sorted_query, query)
|
||||
|
||||
def test_get_object_url(self):
|
||||
self.pyramid_config.add_route('people.view', '/people/{uuid}')
|
||||
model = self.app.model
|
||||
typ = mod.PersonRef(self.request, session=self.session)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.PersonRef(self.request)
|
||||
|
||||
person = model.Person(full_name="Barney Rubble")
|
||||
self.session.add(person)
|
||||
self.session.commit()
|
||||
person = model.Person(full_name="Barney Rubble")
|
||||
self.session.add(person)
|
||||
self.session.commit()
|
||||
|
||||
url = typ.get_object_url(person)
|
||||
self.assertIsNotNone(url)
|
||||
self.assertIn(f'/people/{person.uuid}', url)
|
||||
url = typ.get_object_url(person)
|
||||
self.assertIsNotNone(url)
|
||||
self.assertIn(f'/people/{person.uuid}', url)
|
||||
|
||||
|
||||
class TestRoleRef(WebTestCase):
|
||||
|
||||
def test_sort_query(self):
|
||||
typ = mod.RoleRef(self.request, session=self.session)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
sorted_query = typ.sort_query(query)
|
||||
self.assertIsInstance(sorted_query, orm.Query)
|
||||
self.assertIsNot(sorted_query, query)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.RoleRef(self.request)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
sorted_query = typ.sort_query(query)
|
||||
self.assertIsInstance(sorted_query, orm.Query)
|
||||
self.assertIsNot(sorted_query, query)
|
||||
|
||||
def test_get_object_url(self):
|
||||
self.pyramid_config.add_route('roles.view', '/roles/{uuid}')
|
||||
model = self.app.model
|
||||
typ = mod.RoleRef(self.request, session=self.session)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.RoleRef(self.request)
|
||||
|
||||
role = model.Role(name='Manager')
|
||||
self.session.add(role)
|
||||
self.session.commit()
|
||||
role = model.Role(name='Manager')
|
||||
self.session.add(role)
|
||||
self.session.commit()
|
||||
|
||||
url = typ.get_object_url(role)
|
||||
self.assertIsNotNone(url)
|
||||
self.assertIn(f'/roles/{role.uuid}', url)
|
||||
url = typ.get_object_url(role)
|
||||
self.assertIsNotNone(url)
|
||||
self.assertIn(f'/roles/{role.uuid}', url)
|
||||
|
||||
|
||||
class TestUserRef(WebTestCase):
|
||||
|
||||
def test_sort_query(self):
|
||||
typ = mod.UserRef(self.request, session=self.session)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
sorted_query = typ.sort_query(query)
|
||||
self.assertIsInstance(sorted_query, orm.Query)
|
||||
self.assertIsNot(sorted_query, query)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.UserRef(self.request)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
sorted_query = typ.sort_query(query)
|
||||
self.assertIsInstance(sorted_query, orm.Query)
|
||||
self.assertIsNot(sorted_query, query)
|
||||
|
||||
def test_get_object_url(self):
|
||||
self.pyramid_config.add_route('users.view', '/users/{uuid}')
|
||||
model = self.app.model
|
||||
typ = mod.UserRef(self.request, session=self.session)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.UserRef(self.request)
|
||||
|
||||
user = model.User(username='barney')
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
user = model.User(username='barney')
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
url = typ.get_object_url(user)
|
||||
self.assertIsNotNone(url)
|
||||
self.assertIn(f'/users/{user.uuid}', url)
|
||||
url = typ.get_object_url(user)
|
||||
self.assertIsNotNone(url)
|
||||
self.assertIn(f'/users/{user.uuid}', url)
|
||||
|
||||
|
||||
class TestUserRefs(DataTestCase):
|
||||
|
@ -320,9 +333,10 @@ class TestUserRefs(DataTestCase):
|
|||
|
||||
def test_widget_maker(self):
|
||||
model = self.app.model
|
||||
typ = mod.UserRefs(self.request, session=self.session)
|
||||
widget = typ.widget_maker()
|
||||
self.assertIsInstance(widget, widgets.UserRefsWidget)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
typ = mod.UserRefs(self.request)
|
||||
widget = typ.widget_maker()
|
||||
self.assertIsInstance(widget, widgets.UserRefsWidget)
|
||||
|
||||
|
||||
class TestRoleRefs(DataTestCase):
|
||||
|
@ -341,20 +355,22 @@ class TestRoleRefs(DataTestCase):
|
|||
self.session.add(blokes)
|
||||
self.session.commit()
|
||||
|
||||
# with root access, default values include: admin, blokes
|
||||
self.request.is_root = True
|
||||
typ = mod.RoleRefs(self.request, session=self.session)
|
||||
widget = typ.widget_maker()
|
||||
self.assertEqual(len(widget.values), 2)
|
||||
self.assertEqual(widget.values[0][1], "Administrator")
|
||||
self.assertEqual(widget.values[1][1], "Blokes")
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
|
||||
# without root, default values include: blokes
|
||||
self.request.is_root = False
|
||||
typ = mod.RoleRefs(self.request, session=self.session)
|
||||
widget = typ.widget_maker()
|
||||
self.assertEqual(len(widget.values), 1)
|
||||
self.assertEqual(widget.values[0][1], "Blokes")
|
||||
# with root access, default values include: admin, blokes
|
||||
self.request.is_root = True
|
||||
typ = mod.RoleRefs(self.request)
|
||||
widget = typ.widget_maker()
|
||||
self.assertEqual(len(widget.values), 2)
|
||||
self.assertEqual(widget.values[0][1], "Administrator")
|
||||
self.assertEqual(widget.values[1][1], "Blokes")
|
||||
|
||||
# without root, default values include: blokes
|
||||
self.request.is_root = False
|
||||
typ = mod.RoleRefs(self.request)
|
||||
widget = typ.widget_maker()
|
||||
self.assertEqual(len(widget.values), 1)
|
||||
self.assertEqual(widget.values[0][1], "Blokes")
|
||||
|
||||
|
||||
class TestPermissions(DataTestCase):
|
||||
|
|
|
@ -10,6 +10,7 @@ from pyramid import testing
|
|||
|
||||
from wuttaweb import grids
|
||||
from wuttaweb.forms import widgets as mod
|
||||
from wuttaweb.forms import schema
|
||||
from wuttaweb.forms.schema import (FileDownload, PersonRef, RoleRefs, UserRefs, Permissions,
|
||||
WuttaDateTime, EmailRecipients)
|
||||
from tests.util import WebTestCase
|
||||
|
@ -32,31 +33,33 @@ class TestObjectRefWidget(WebTestCase):
|
|||
self.session.add(person)
|
||||
self.session.commit()
|
||||
|
||||
# standard (editable)
|
||||
node = colander.SchemaNode(PersonRef(self.request, session=self.session))
|
||||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid)
|
||||
self.assertIn('<b-select ', html)
|
||||
with patch.object(schema, 'Session', return_value=self.session):
|
||||
|
||||
# readonly
|
||||
node = colander.SchemaNode(PersonRef(self.request, session=self.session))
|
||||
node.model_instance = person
|
||||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid, readonly=True)
|
||||
self.assertIn('Betty Boop', html)
|
||||
self.assertNotIn('<a', html)
|
||||
# standard (editable)
|
||||
node = colander.SchemaNode(PersonRef(self.request))
|
||||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid)
|
||||
self.assertIn('<b-select ', html)
|
||||
|
||||
# with hyperlink
|
||||
node = colander.SchemaNode(PersonRef(self.request, session=self.session))
|
||||
node.model_instance = person
|
||||
widget = self.make_widget(url=lambda p: '/foo')
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid, readonly=True)
|
||||
self.assertIn('Betty Boop', html)
|
||||
self.assertIn('<a', html)
|
||||
self.assertIn('href="/foo"', html)
|
||||
# readonly
|
||||
node = colander.SchemaNode(PersonRef(self.request))
|
||||
node.model_instance = person
|
||||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid, readonly=True)
|
||||
self.assertIn('Betty Boop', html)
|
||||
self.assertNotIn('<a', html)
|
||||
|
||||
# with hyperlink
|
||||
node = colander.SchemaNode(PersonRef(self.request))
|
||||
node.model_instance = person
|
||||
widget = self.make_widget(url=lambda p: '/foo')
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid, readonly=True)
|
||||
self.assertIn('Betty Boop', html)
|
||||
self.assertIn('<a', html)
|
||||
self.assertIn('href="/foo"', html)
|
||||
|
||||
def test_get_template_values(self):
|
||||
model = self.app.model
|
||||
|
@ -64,22 +67,24 @@ class TestObjectRefWidget(WebTestCase):
|
|||
self.session.add(person)
|
||||
self.session.commit()
|
||||
|
||||
# standard
|
||||
node = colander.SchemaNode(PersonRef(self.request, session=self.session))
|
||||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
values = widget.get_template_values(field, person.uuid, {})
|
||||
self.assertIn('cstruct', values)
|
||||
self.assertNotIn('url', values)
|
||||
with patch.object(schema, 'Session', return_value=self.session):
|
||||
|
||||
# readonly w/ empty option
|
||||
node = colander.SchemaNode(PersonRef(self.request, session=self.session,
|
||||
empty_option=('_empty_', '(empty)')))
|
||||
widget = self.make_widget(readonly=True, url=lambda obj: '/foo')
|
||||
field = self.make_field(node)
|
||||
values = widget.get_template_values(field, '_empty_', {})
|
||||
self.assertIn('cstruct', values)
|
||||
self.assertNotIn('url', values)
|
||||
# standard
|
||||
node = colander.SchemaNode(PersonRef(self.request))
|
||||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
values = widget.get_template_values(field, person.uuid, {})
|
||||
self.assertIn('cstruct', values)
|
||||
self.assertNotIn('url', values)
|
||||
|
||||
# readonly w/ empty option
|
||||
node = colander.SchemaNode(PersonRef(self.request,
|
||||
empty_option=('_empty_', '(empty)')))
|
||||
widget = self.make_widget(readonly=True, url=lambda obj: '/foo')
|
||||
field = self.make_field(node)
|
||||
values = widget.get_template_values(field, '_empty_', {})
|
||||
self.assertIn('cstruct', values)
|
||||
self.assertNotIn('url', values)
|
||||
|
||||
|
||||
class TestWuttaDateTimeWidget(WebTestCase):
|
||||
|
@ -230,28 +235,29 @@ class TestRoleRefsWidget(WebTestCase):
|
|||
self.session.commit()
|
||||
|
||||
# nb. we let the field construct the widget via our type
|
||||
node = colander.SchemaNode(RoleRefs(self.request, session=self.session))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
with patch.object(schema, 'Session', return_value=self.session):
|
||||
node = colander.SchemaNode(RoleRefs(self.request))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
|
||||
# readonly values list includes admin
|
||||
html = widget.serialize(field, {admin.uuid, blokes.uuid}, readonly=True)
|
||||
self.assertIn(admin.name, html)
|
||||
self.assertIn(blokes.name, html)
|
||||
# readonly values list includes admin
|
||||
html = widget.serialize(field, {admin.uuid, blokes.uuid}, readonly=True)
|
||||
self.assertIn(admin.name, html)
|
||||
self.assertIn(blokes.name, html)
|
||||
|
||||
# editable values list *excludes* admin (by default)
|
||||
html = widget.serialize(field, {admin.uuid, blokes.uuid})
|
||||
self.assertNotIn(str(admin.uuid.hex), html)
|
||||
self.assertIn(str(blokes.uuid.hex), html)
|
||||
# editable values list *excludes* admin (by default)
|
||||
html = widget.serialize(field, {admin.uuid, blokes.uuid})
|
||||
self.assertNotIn(str(admin.uuid.hex), html)
|
||||
self.assertIn(str(blokes.uuid.hex), html)
|
||||
|
||||
# but admin is included for root user
|
||||
self.request.is_root = True
|
||||
node = colander.SchemaNode(RoleRefs(self.request, session=self.session))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
html = widget.serialize(field, {admin.uuid, blokes.uuid})
|
||||
self.assertIn(str(admin.uuid.hex), html)
|
||||
self.assertIn(str(blokes.uuid.hex), html)
|
||||
# but admin is included for root user
|
||||
self.request.is_root = True
|
||||
node = colander.SchemaNode(RoleRefs(self.request))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
html = widget.serialize(field, {admin.uuid, blokes.uuid})
|
||||
self.assertIn(str(admin.uuid.hex), html)
|
||||
self.assertIn(str(blokes.uuid.hex), html)
|
||||
|
||||
|
||||
class TestUserRefsWidget(WebTestCase):
|
||||
|
@ -266,35 +272,37 @@ class TestUserRefsWidget(WebTestCase):
|
|||
model = self.app.model
|
||||
|
||||
# nb. we let the field construct the widget via our type
|
||||
node = colander.SchemaNode(UserRefs(self.request, session=self.session))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
# node = colander.SchemaNode(UserRefs(self.request, session=self.session))
|
||||
with patch.object(schema, 'Session', return_value=self.session):
|
||||
node = colander.SchemaNode(UserRefs(self.request))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
|
||||
# readonly is required
|
||||
self.assertRaises(NotImplementedError, widget.serialize, field, set())
|
||||
self.assertRaises(NotImplementedError, widget.serialize, field, set(), readonly=False)
|
||||
# readonly is required
|
||||
self.assertRaises(NotImplementedError, widget.serialize, field, set())
|
||||
self.assertRaises(NotImplementedError, widget.serialize, field, set(), readonly=False)
|
||||
|
||||
# empty
|
||||
html = widget.serialize(field, set(), readonly=True)
|
||||
self.assertEqual(html, '<span></span>')
|
||||
# empty
|
||||
html = widget.serialize(field, set(), readonly=True)
|
||||
self.assertEqual(html, '<span></span>')
|
||||
|
||||
# with data, no actions
|
||||
user = model.User(username='barney')
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
html = widget.serialize(field, {user.uuid}, readonly=True)
|
||||
self.assertIn('<b-table ', html)
|
||||
self.assertNotIn('Actions', html)
|
||||
self.assertNotIn('View', html)
|
||||
self.assertNotIn('Edit', html)
|
||||
|
||||
# with view/edit actions
|
||||
with patch.object(self.request, 'is_root', new=True):
|
||||
# with data, no actions
|
||||
user = model.User(username='barney')
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
html = widget.serialize(field, {user.uuid}, readonly=True)
|
||||
self.assertIn('<b-table ', html)
|
||||
self.assertIn('Actions', html)
|
||||
self.assertIn('View', html)
|
||||
self.assertIn('Edit', html)
|
||||
self.assertIn('<b-table ', html)
|
||||
self.assertNotIn('Actions', html)
|
||||
self.assertNotIn('View', html)
|
||||
self.assertNotIn('Edit', html)
|
||||
|
||||
# with view/edit actions
|
||||
with patch.object(self.request, 'is_root', new=True):
|
||||
html = widget.serialize(field, {user.uuid}, readonly=True)
|
||||
self.assertIn('<b-table ', html)
|
||||
self.assertIn('Actions', html)
|
||||
self.assertIn('View', html)
|
||||
self.assertIn('Edit', html)
|
||||
|
||||
|
||||
class TestPermissionsWidget(WebTestCase):
|
||||
|
@ -318,7 +326,7 @@ class TestPermissionsWidget(WebTestCase):
|
|||
}
|
||||
|
||||
# nb. we let the field construct the widget via our type
|
||||
node = colander.SchemaNode(Permissions(self.request, permissions, session=self.session))
|
||||
node = colander.SchemaNode(Permissions(self.request, permissions))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue