Hi everyone,
I have a problem in tg2 displaying records in turbogears
Administration System. I created two tables and a view in this way:
adresses (table):
address_id
str_number
street
unit_type
unit number
city
state
post_code
persons (table):
person_id
first_name
last_name
dob
address_id
there is a foreign key from adresses.address_id on persons.address_id
persons_view
person_id
first_name
last_name
dob
address = addresses.str_number +' '+ addresses.street+'
'+addresses.city (defined in postgresql database in the appropriate
way, || instead of +)
my model/__init__.py looks like (reflected tables and a view):
# -*- coding: utf-8 -*-
"""The application's model objects"""
from zope.sqlalchemy import ZopeTransactionExtension
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.orm import mapper, relation
from sqlalchemy import Table
from sqlalchemy.ext.declarative import declarative_base
maker = sessionmaker(autoflush=True, autocommit=False,
extension=ZopeTransactionExtension())
DBSession = scoped_session(maker)
DeclarativeBase = declarative_base()
metadata = DeclarativeBase.metadata
class Persons(object):
def __init__ (self, **kw):
for key, value in kw.iteritems():
setattr(self, key, value)
class Persons_view(object):
def __init__(self, **kw):
for key, value in kw.iteritems():
setattr(self, key, value)
class Addresses(object):
def __init__(self, **kw):
for key, value in kw.iteritems():
setattr(self, key, value)
def init_model(engine):
"""Call me before using any of the tables or classes in the
model."""
DBSession.configure(bind=engine)
persons_table = Table('persons', metadata, autoload=True,
autoload_with=engine)
mapper(Persons, persons_table)
addresses_table = Table('addresses', metadata, autoload=True,
autoload_with=engine)
mapper(Addresses, addresses_table)
persons_view = Table('persons_view', metadata, autoload=True,
autoload_with=engine)
mapper(Persons_view, persons_view, primary_key=
[persons_view.c.person_id])
# Import your model modules here.
from problem.model.auth import User, Group, Permission
To quickstarted controllers/root.py I added:
from problem.model import Addresses, Persons, Persons_view
from problem.controllers.test import test
and in RootController:
admin_alternative = test
Here is my controllers/test.py:
# -*- coding: utf-8 -*-
"""Sample controller module"""
# turbogears imports
from tg import expose
from tgext.crud import CrudRestController
from tg import redirect, validate, flash, config
from tw.core import WidgetsList
from tw.forms import *
#from formencode import validators
from formencode.validators import *
# Admin Controller imports
from tgext.admin import AdminController, AdminConfig,
CrudRestControllerConfig
#from upute import model
# third party imports
from pylons.i18n import ugettext as _
from repoze.what import predicates
# project specific imports
from upute.lib.base import BaseController
from problem import model
from problem.model import *
from sprox.tablebase import TableBase
from sprox.fillerbase import TableFiller, EditFormFiller
from sprox.formbase import AddRecordForm, EditableForm
from sprox.dojo.tablebase import DojoTableBase
from sprox.dojo.fillerbase import DojoTableFiller
__all__= ['test_kontroler']
# Creatin a list of items for SingleSelectField
def comboBox(redovi, polje_sifra, polja_lista):
lista=[(None, None),]
for red in redovi:
red_lista=[]
for polje in polja_lista:
i=red.__getattribute__(polje)
if type(i) is not unicode:
i=unicode(i)
red_lista.append(i)
red_string = u" ".join(red_lista)
lista.append((red.__getattribute__(polje_sifra), red_string))
return lista
class Persons_form(TableBase):
__model__ = Persons
__omit_fields__ = ['person_id']
__field_order__ = ['last_name', 'first_name', 'dob']
__headers__ = {'last_name' : 'Last Name',
'first_name' : 'First Name',
'dob' : 'Date of Birth',
'address_id' : 'Address_ID'}
class Persons_filler(TableFiller):
__model__ = Persons
class Persons_view_form(DojoTableBase):
__model__ = Persons_view
__omit_fields__ = ['person_id']
__field_order__ = ['last_name', 'first_name', 'dob']
__headers__ = {'last_name' : 'Last Name',
'first_name' : 'First Name',
'dob' : 'Date of Birth',
'address' : 'Address'}
class Persons_view_filler(DojoTableFiller):
__model__ = Persons_view
class Persons_add_form(AddRecordForm):
def addresses(): return comboBox(DBSession.query
(Addresses).order_by(Addresses.str_number), 'address_id',
['str_number', 'street', 'city', 'state'])
__model__ = Persons
__require_fields__ = []
__omit_fields__ = ['person_id']
__field_order__ = ['last_name', 'first_name', 'dob',
'address_id']
# Overrided Fields
address_id = SingleSelectField('address_id', label=_(u'Address'),
options=addresses)
class Persons_edit_form(EditableForm):
def addresses(): return comboBox(DBSession.query
(Addresses).order_by(Addresses.str_number), 'address_id',
['str_number', 'street', 'city', 'state'])
__model__ = Persons
__require_fields__ = []
__omit_fields__ = ['sifra_podnositelja']
__field_order__ = ['ime', 'prezime', 'spol', 'mbg', 'oib',
'datum_rod', 'mjesto_rod', 'zemlja_rod', 'prebivaliste', 'boraviste',
'tel', 'fax', 'e-mail', 'odnos_prema_osobi', 'sifra_osobe']
# Overrided Fields
address_id = SingleSelectField('address_id', label=_(u'Address'),
options=addresses)
class Persons_edit_filler(EditFormFiller):
__model__ = Persons
class Persons_config(CrudRestControllerConfig):
table_type = Persons_form
table_filler_type = Persons_filler
# table_type = Persons_view_form
# table_filler_type = Persons_view_filler
new_form_type = Persons_add_form
edit_form_type = Persons_edit_form
edit_filler_type = Persons_edit_filler
class Configuration(AdminConfig):
persons = Persons_config
test = AdminController(model, DBSession, config_type=Configuration)
When I go to http://localhost:8088/admin_alternative/personss instead
of a record a get "No records found" despite the fact there are
records. When I subclass Persons_form and Persons_filler from
DojoTableForm and reapectively, DojoTableFiller I can see the record.
Then I tried using persons_view instead of persons (so I would have
meaningfull address instead of address_id) so class Persons_config
looks like:
class Persons_config(CrudRestControllerConfig):
#table_type = Persons_form
#table_filler_type = Persons_filler
table_type = Persons_view_form
table_filler_type = Persons_view_filler
new_form_type = Persons_add_form
edit_form_type = Persons_edit_form
edit_filler_type = Persons_edit_filler
but after refreshing the page instead of records I get:
"Sorry, an error occurred"
and debug view gave me:
WebError Traceback:
⇝ TypeError: getattr(): attribute name must be string
View as: Interactive (full) | Text (full) | XML (full)
clear this
clear this
URL: http://192.168.8.15:8088/admin_alternative/personss.json?start=0&count=20
Module weberror.evalexception:431 in respond view
<< try:
__traceback_supplement__ =
errormiddleware.Supplement, self, environ
app_iter = self.application(environ,
detect_start_response)
# Don't create a list from a paste.fileapp object
>> app_iter = self.application(environ, detect_start_response)
Module tg.configuration:655 in wrapper view
<< log.debug("Making request body seekable")
Request(environ).make_body_seekable()
return app(environ, start_response)
return wrapper
>> return app(environ, start_response)
Module tg.configuration:555 in remover view
<< def remover(environ, start_response):
try:
return app(environ, start_response)
finally:
log.debug("Removing DBSession from current
thread")
>> return app(environ, start_response)
Module repoze.tm:19 in __call__ view
<< return start_response(status, headers, exc_info)
try:
result = self.application(environ,
save_status_and_headers)
except:
self.abort()
>> result = self.application(environ, save_status_and_headers)
Module repoze.who.middleware:107 in __call__ view
<< wrapper = StartResponseWrapper(start_response)
app_iter = app(environ, wrapper.wrap_start_response)
# The challenge decider almost(?) always needs
information from the
>> app_iter = app(environ, wrapper.wrap_start_response)
Module tw.core.middleware:43 in __call__ view
<< def __call__(self, environ, start_response):
return self.wsgi_app(environ, start_response)
def wsgi_app(self, environ, start_response):
>> return self.wsgi_app(environ, start_response)
Module tw.core.middleware:68 in wsgi_app view
<< else:
# Pass request downstream
resp = req.get_response(self.application)
return resp(environ, start_response)
finally:
>> resp = req.get_response(self.application)
Module webob:1325 in get_response view
Module webob:1293 in call_application view
Module tw.core.resource_injector:68 in _injector view
<< def _injector(environ, start_response):
req = Request(environ)
resp = req.get_response(app)
content_type = resp.headers.get('Content-Type','text/
plain').lower()
if 'html' in content_type:
>> resp = req.get_response(app)
Module webob:1325 in get_response view
Module webob:1293 in call_application view
Module beaker.middleware:81 in __call__ view
<<
self.cache_manager)
environ[self.environ_key] = self.cache_manager
return self.app(environ, start_response)
>> return self.app(environ, start_response)
Module beaker.middleware:160 in __call__ view
<< headers.append(('Set-cookie', cookie))
return start_response(status, headers, exc_info)
return self.wrap_app(environ, session_start_response)
def _get_session(self):
>> return self.wrap_app(environ, session_start_response)
Module routes.middleware:130 in __call__ view
<< environ['SCRIPT_NAME'] = environ['SCRIPT_NAME']
[:-1]
response = self.app(environ, start_response)
# Wrapped in try as in rare cases the attribute will be
gone already
>> response = self.app(environ, start_response)
Module pylons.wsgiapp:125 in __call__ view
<<
controller = self.resolve(environ, start_response)
response = self.dispatch(controller, environ,
start_response)
if 'paste.testing_variables' in environ and hasattr
(response,
>> response = self.dispatch(controller, environ, start_response)
Module pylons.wsgiapp:324 in dispatch view
<< if log_debug:
log.debug("Calling controller class with WSGI
interface")
return controller(environ, start_response)
def load_test_env(self, environ):
>> return controller(environ, start_response)
Module problem.lib.base:32 in __call__ view
<< request.identity = request.environ.get
('repoze.who.identity')
tmpl_context.identity = request.identity
return TGController.__call__(self, environ,
start_response)
>> return TGController.__call__(self, environ, start_response)
Module pylons.controllers.core:221 in __call__ view
<< return response(environ, self.start_response)
response = self._dispatch_call()
if not start_response_called:
self.start_response = start_response
>> response = self._dispatch_call()
Module pylons.controllers.core:172 in _dispatch_call view
<< req.environ['pylons.action_method'] = func
response = self._inspect_call(func)
else:
if log_debug:
>> response = self._inspect_call(func)
Module pylons.controllers.core:107 in _inspect_call view
<< func.__name__, args)
try:
result = self._perform_call(func, args)
except HTTPException, httpe:
if log_debug:
>> result = self._perform_call(func, args)
Module tg.controllers:857 in _perform_call view
<< return
result = DecoratedController._perform_call(
self, controller, params, remainder=remainder)
except HTTPException, httpe:
>> self, controller, params, remainder=remainder)
Module tg.controllers:172 in _perform_call view
<< remainder[i] = params[name]
del params[name]
output = controller(*remainder, **dict(params))
except formencode.api.Invalid, inv:
>> output = controller(*remainder, **dict(params))
Module ?:2 in get_all view
Module tg.decorators:560 in with_trailing_slash view
<< from tg.controllers import redirect
redirect(request.url+'/')
return func(*args, **kwargs)
#{ Authorization decorators
>> return func(*args, **kwargs)
Module tgext.crud.controller:92 in get_all view
Module sprox.dojo.fillerbase:23 in get_value view
<< order_by = order_by[1:]
desc = True
items = super(DojoTableFiller, self).get_value(value,
limit=limit, offset=offset, order_by=order_by, desc=desc, **kw)
count = self.get_count()
identifier = self.__provider__.get_primary_field
(self.__entity__)
>> items = super(DojoTableFiller, self).get_value(value, limit=limit,
>> offset=offset, order_by=order_by, desc=desc, **kw)
Module sprox.fillerbase:201 in get_value view
<< value = getattr(self, field)(obj, **kw)
else:
value = getattr(self, field)(obj)
else:
value = getattr(obj, field)
>> value = getattr(self, field)(obj)
Module sprox.fillerbase:155 in __actions__ view
<< """Override this function to define how action links
should be displayed for the given record."""
primary_fields = self.__provider__.get_primary_fields
(self.__entity__)
pklist = '/'.join(map(lambda x: str(getattr(obj, x)),
primary_fields))
value = '<div><div> <a href="'+pklist+'/edit"
style="text-decoration:none">edit</a>'\
'</div><div>'\
>> pklist = '/'.join(map(lambda x: str(getattr(obj, x)), primary_fields))
Module sprox.fillerbase:155 in <lambda> view
<< """Override this function to define how action links
should be displayed for the given record."""
primary_fields = self.__provider__.get_primary_fields
(self.__entity__)
pklist = '/'.join(map(lambda x: str(getattr(obj, x)),
primary_fields))
value = '<div><div> <a href="'+pklist+'/edit"
style="text-decoration:none">edit</a>'\
'</div><div>'\
>> pklist = '/'.join(map(lambda x: str(getattr(obj, x)), primary_fields))
TypeError: getattr(): attribute name must be string
I have 2 questions:
1. Why does not a form subclassed from TableBase and TableFiller show
records
2. What is the difference in showing records from a table compared to
showing records from a view
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"TurboGears" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/turbogears?hl=en
-~----------~----~----~----~------~----~------~--~---