Search code examples
pythonjsonrestpyramidtraceback

Issue rendering a List Object: AttributeError: 'list' object has no attribute '...'


I am attempting to render good ol' JSON via return {'category_name': category.category_name}in a views.py file. I am using Pyramid Web Framework. I am using a custom RESTful web api and a CRUD design in the SQLALCHEMY database.

For some reason, I keep getting the Traceback error:

views/views.py", line 112, in get_category
    return {'category': category.category_name}
AttributeError: 'list' object has no attribute 'category_name'

All I want to do is print this out to HTML or render it to HTML so that I can see what was created. Category does have the attribute category_name...which is confusing. Perhaps to return a list value, I have to use special syntax? I couldn't find anything online that made sense to me (this was the most relevant), but any guidance would be greatly appreciated! I am sure it is something simple.

GET method: site of the return object (meant to render on Jinja2 templates later):

@view_config(route_name='category', request_method='GET', renderer='json')
def get_category(request):
    with transaction.manager:
        category_id = int(request.matchdict['id'])
        category = api.retrieve_category(category_id)
        if category is None:
            raise HTTPNotFound()
        return {'category_name': category.category_name}

This is what the POST method looks like (very much like the Create function in the DB api):

@view_config(route_name='categories', request_method='POST', renderer='json')
def post_category(request):
    with transaction.manager:
        category_name = request.params['category_name']
        category = api.create_category(category_name)
        return HTTPCreated(location=request.route_url('category',id=id))

DB API for creating a category (this has a Many-to-Many relationship with Assessment, thus the list):

def create_category(self, category_name):
    new_category = Category(category_name)
    self.session.add(new_category)
    print(new_category)
    self.session.commit()

Retrieve method:

def retrieve_category(self, something_unique):
    if isinstance(something_unique, int):
        return self.session.query(Category).\
        filter(Category.category_id == something_unique).all() # multiple categories
    elif isinstance(something_unique, basestring):
        print(something_unique) # added
        return self.session.query(Category).\
        filter(Category.category_name == something_unique).one()
        print(something_unique)
        if NoResultFound:
            raise NotFoundError('No results found')
        elif MultipleResultsFound:
            raise MultipleResultsFound('Too many results found')
    elif isinstance(something_unique, Category):
        return something_unique
    else:
        raise ValueError('Value being passed is an object')

convenience api (inheritance):

def create_assessment(self, name, text, username, videoname, category_names):
    user = self.retrieve_user(username)
    video = self.retrieve_video(videoname)
    cat_objects = [self.retrieve_category(category_name) for category_name in category_names]
    return super(ConvenienceAPI, self).create_assessment(name, text, user, video, cat_objects)

Solution

  • api.retrieve_category() is returning a list, as the exception shows. What are you expecting it to return?

    You need to check what your API is returning. Possibly you could access the first item in the returned list so this might work:

    return {'category_name': category[0].category_name}
    

    However, if the API is actually returning an empty list ([]) to signify no result, then you need to check for that rather than for None:

    if not category:
        raise HTTPNotFound()