Skip to content

AttributeError: type object '<model>' has no attribute '' #8

@hroncok

Description

@hroncok

Given the following example (search for HERE IS THE PROBLEM):

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask_ripozo import FlaskDispatcher
from ripozo import restmixins, ListRelationship, Relationship, adapters, apimethod
from ripozo_sqlalchemy import AlchemyManager, SessionHandler
from sqlalchemy.engine.url import URL
from sqlalchemy.orm import relationship

app = Flask(__name__)
url = URL('mysql', query={'read_default_file': './mysql.cnf'})
app.config['SQLALCHEMY_DATABASE_URI'] = url
db = SQLAlchemy(app)


session_handler = SessionHandler(db.session)

class Sport(db.Model):
    __tablename__ = 'v_sports'

    id_sport = db.Column(db.Integer, primary_key=True)
    description = db.Column(db.String)


class Course(db.Model):
    __tablename__ = 'v_subjects'

    id_course = db.Column('id_subjects', db.Integer, primary_key=True)
    _sport = db.Column('sport', db.Integer, db.ForeignKey('v_sports.id_sport'))
    sport = relationship(Sport, foreign_keys=(_sport,))     # <--- HERE IS THE PROBLEM


class SportManager(AlchemyManager):
    fields = ('id_sport', 'description',)
    model = Sport


class CourseManager(AlchemyManager):
    fields = ('id_course', 'sport',)
    model = Course


class SportResource(restmixins.RetrieveRetrieveList):
    manager = SportManager(session_handler)
    resource_name = 'sports'
    pks = ('id_sport',)


class CourseResource(restmixins.RetrieveRetrieveList):
    manager = CourseManager(session_handler)
    resource_name = 'courses'
    pks = ('id_course',)

dispatcher = FlaskDispatcher(app, url_prefix='/')
dispatcher.register_resources(SportResource, CourseResource)
dispatcher.register_adapters(adapters.BasicJSONAdapter)

if __name__ == '__main__':
    app.run(debug=True)

If I GET /courses/1/, I get a nasty exception:


type object 'Sport' has no attribute ''
Traceback (most recent call last):
  File "venv/lib64/python3.4/site-packages/ripozo_sqlalchemy/alchemymanager.py", line 102, in _get_field_python_type
    return getattr(model, name).property.columns[0].type.python_type
  File "venv/lib64/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 840, in __getattr__
    return self._fallback_getattr(key)
  File "venv/lib64/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 818, in _fallback_getattr
    raise AttributeError(key)
AttributeError: columns

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "venv/lib64/python3.4/site-packages/ripozo_sqlalchemy/alchemymanager.py", line 102, in _get_field_python_type
    return getattr(model, name).property.columns[0].type.python_type
AttributeError: type object 'Sport' has no attribute ''

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "venv/lib64/python3.4/site-packages/flask_ripozo/dispatcher.py", line 213, in flask_dispatch
    adapter = dispatcher.dispatch(f, accepted_mimetypes, ripozo_request)
  File "venv/lib64/python3.4/site-packages/ripozo/dispatch_base.py", line 212, in dispatch
    result = endpoint_func(request, *args, **kwargs)
  File "venv/lib64/python3.4/site-packages/ripozo/decorators.py", line 103, in newfunc
    return self.func(klass, *args)
  File "venv/lib64/python3.4/site-packages/ripozo/decorators.py", line 197, in wrapped
    resource = func(cls, request, *args, **kwargs)
  File "venv/lib64/python3.4/site-packages/ripozo/decorators.py", line 111, in __call__
    return self.__get__(None, klass=cls)(*args, **kwargs)
  File "venv/lib64/python3.4/site-packages/ripozo/decorators.py", line 103, in newfunc
    return self.func(klass, *args)
  File "venv/lib64/python3.4/site-packages/ripozo/decorators.py", line 367, in action
    translate_fields(request, self.fields(cls.manager),
  File "venv/lib64/python3.4/site-packages/ripozo/decorators.py", line 382, in fields
    for field in manager.field_validators:
  File "venv/lib64/python3.4/site-packages/ripozo/decorators.py", line 33, in __get__
    return self.fget.__get__(obj, klass)()
  File "venv/lib64/python3.4/site-packages/ripozo/manager_base.py", line 208, in field_validators
    cls._field_validators[field_name] = cls.get_field_type(field_name)
  File "venv/lib64/python3.4/site-packages/ripozo_sqlalchemy/alchemymanager.py", line 123, in get_field_type
    python_type = cls._get_field_python_type(cls.model, name)
  File "venv/lib64/python3.4/site-packages/ripozo_sqlalchemy/alchemymanager.py", line 106, in _get_field_python_type
    return AlchemyManager._get_field_python_type(model, '.'.join(parts))
  File "venv/lib64/python3.4/site-packages/ripozo_sqlalchemy/alchemymanager.py", line 105, in _get_field_python_type
    model = getattr(model, parts.pop(0)).comparator.mapper.class_
AttributeError: type object 'Sport' has no attribute ''
127.0.0.1 - - [25/Apr/2016 20:24:18] "GET /courses/117/ HTTP/1.1" 500 -
Traceback (most recent call last):
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "venv/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "venv/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "venv/lib/python3.4/site-packages/flask_ripozo/dispatcher.py", line 216, in flask_dispatch
    return dispatcher.error_handler(dispatcher, accepted_mimetypes, e)
  File "venv/lib/python3.4/site-packages/flask_ripozo/dispatcher.py", line 51, in exception_handler
    raise exc
  File "venv/lib/python3.4/site-packages/flask_ripozo/dispatcher.py", line 213, in flask_dispatch
    adapter = dispatcher.dispatch(f, accepted_mimetypes, ripozo_request)
  File "venv/lib/python3.4/site-packages/ripozo/dispatch_base.py", line 212, in dispatch
    result = endpoint_func(request, *args, **kwargs)
  File "venv/lib/python3.4/site-packages/ripozo/decorators.py", line 103, in newfunc
    return self.func(klass, *args)
  File "venv/lib/python3.4/site-packages/ripozo/decorators.py", line 197, in wrapped
    resource = func(cls, request, *args, **kwargs)
  File "venv/lib/python3.4/site-packages/ripozo/decorators.py", line 111, in __call__
    return self.__get__(None, klass=cls)(*args, **kwargs)
  File "venv/lib/python3.4/site-packages/ripozo/decorators.py", line 103, in newfunc
    return self.func(klass, *args)
  File "venv/lib/python3.4/site-packages/ripozo/decorators.py", line 367, in action
    translate_fields(request, self.fields(cls.manager),
  File "venv/lib/python3.4/site-packages/ripozo/decorators.py", line 382, in fields
    for field in manager.field_validators:
  File "venv/lib/python3.4/site-packages/ripozo/decorators.py", line 33, in __get__
    return self.fget.__get__(obj, klass)()
  File "venv/lib/python3.4/site-packages/ripozo/manager_base.py", line 208, in field_validators
    cls._field_validators[field_name] = cls.get_field_type(field_name)
  File "venv/lib/python3.4/site-packages/ripozo_sqlalchemy/alchemymanager.py", line 123, in get_field_type
    python_type = cls._get_field_python_type(cls.model, name)
  File "venv/lib/python3.4/site-packages/ripozo_sqlalchemy/alchemymanager.py", line 106, in _get_field_python_type
    return AlchemyManager._get_field_python_type(model, '.'.join(parts))
  File "venv/lib/python3.4/site-packages/ripozo_sqlalchemy/alchemymanager.py", line 105, in _get_field_python_type
    model = getattr(model, parts.pop(0)).comparator.mapper.class_
AttributeError: type object 'Sport' has no attribute ''

The problem is here: https://github.com/vertical-knowledge/ripozo-sqlalchemy/blob/master/ripozo_sqlalchemy/alchemymanager.py#L106

The joined part is empty string.

But even when I remove that and return just object, as it was previously before 4445a19 I still get weird errors.

Traceback (most recent call last):
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "venv/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "venv/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "venv/lib/python3.4/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "venv/lib/python3.4/site-packages/flask_ripozo/dispatcher.py", line 218, in flask_dispatch
    return Response(response=adapter.formatted_body, headers=adapter.extra_headers,
  File "venv/lib/python3.4/site-packages/ripozo/adapters/basic_json.py", line 59, in formatted_body
    return json.dumps({self.resource.resource_name: response})
  File "/usr/lib64/python3.4/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib64/python3.4/json/encoder.py", line 192, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib64/python3.4/json/encoder.py", line 250, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib64/python3.4/json/encoder.py", line 173, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <__main__.Sport object at 0x7f0079dc62e8> is not JSON serializable

What am I doing wrong? I've spend couple of hours trying and I'm clueless.

Thanks for any help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions