I am pretty new to using both SQLALCHEMY and the PYRAMID web framework. I am struggling with what might be a simple fix to some, but I haven't been able to figure it out. I have looked at some posts here on Stacks, but they don't quite answer my issue.
I have a many-to-many relationship in my database table. I am trying to return an object (categories) from the parent table assessment. I am trying at the moment to: return {'name': assessment.name, 'text': assessment.text, 'user': assessment.user_id, 'video':assessment.video_id, 'categories': assessment.categories.assessment_category_link} but this doesn't work --> 'categories': assessment.categories.assessment_category_link
I am able to return all the objects except categories. Below is the relevant error and code.
TRACEBACK:
line 306, in get_assessment
return {'name': assessment.name, 'text': assessment.text, 'user': assessment.user_id, 'video':assessment.video_id, 'categories': assessment.categories.assessment_category_link}
AttributeError: 'InstrumentedList' object has no attribute 'assessment_category_link'
SQLALCHEMY TABLE/RELATIONSHIP:
# MANY-to-MANY
association_table = Table('assessment_category_link', Base.metadata,
Column('assessment_id', Integer, ForeignKey('assessments.assessment_id')),
Column('category_id', Integer, ForeignKey('categories.category_id')))
class Assessment(Base):
# column/entity code
categories = relationship('Category', secondary='assessment_category_link', backref='assessments')
def __init__(self, name, text, user, video, categories):
# CODE
self.categories = categories
The GET() method, specifically the return value that is throwing the error:
#view_config(route_name='assessment', request_method='GET', renderer='json')
def get_assessment(request):
with transaction.manager:
assessment_id = int(request.matchdict['id'])
assessment = api.retrieve_assessment(assessment_id)
if not assessment:
raise HTTPNotFound()
return {'name': assessment.name, 'text': assessment.text, 'user': assessment.user_id, 'video':assessment.video_id, 'categories': assessment.categories.assessment_category_link}
I am not sure what you are trying to achieve since assessment.categories would return a list of Category objects that you need to iterate over. It is logical for such a list not to have an attribute named assessment_category_link (as the exception tells you), and it is not clear to me why you would want to access the association object anyway!
The relationship with the secondary keyword argument is meant to hide this complexity away so that assessment.categories would transparently return the list that you're after.
you can represent the categories list as you like, a suggestion for your case:
{...., 'categories': ', '.join([str(i) for i in assessment.categories])}
The answer above was very close, but the working code is:
{...., 'categories': ','.join([str(i) for i in assessment.categories])}
As suggested by similar Stack question/answer to the same issue: TypeError: sequence item 0: expected string, int found
Related
I'm customizing the Odoo project module, in the module, we have Projects that have tasks assigned to employees, I need to have a dropdown of employees based on the project selection, but because there isn't a direct relation I have to search all the tasks related to the project and then search for the employees.
this is my model so far:
class myModel(models.TransientModel):
_name = "mymodule.mymodel"
project_id = fields.Many2one('project.project', string="Project")
task_id = fields.Many2one('project.task', string="Task", domain="[('project_id', '=', project_id)]")
employee_id = fields.Many2one('hr.employee', string="Assign To")
#api.onchange('project_id')
def _projecy_onchange(self):
if not self.project_id.id:
return {'domain': {'employee_id': []}}
tasks = self.env['project.task'].search([('project_id','=',self.project_id.id)])
user_ids = []
for t in tasks:
if t.user_id:
user_ids.append(t.user_id.id)
if len(user_ids)>0:
employees = self.env['hr.employee'].search(['user_id','in', user_ids])
return {'domain': {'employee_id': employees}}
else:
return {'domain': {'employee_id': []}}
I'm having an issue when I want to search the employees:
employees = self.env['hr.employee'].search(['user_id','in',
user_ids])
I get the following error:
elif token[1] == 'in' and not token[2]: IndexError: tuple index out
of range
when I print user_ids is a basic list with the ids something like [9] (single element, cloud me more obviously)
I understand search can work as
employees = self.env['hr.employee'].search(['user_id','in', [9])
any guidance will be appreciated
You have got the wrong syntax of odoo's search method do it like this,
employees = self.env['hr.employee'].search([('user_id','in', user_ids)])
Missing part from your syntax: round braces around your domain.
Im trying to add a movie to my mongo DB table but it is only included the last value could someone tell me where I am going wring the code I am using in my python file is below:
#app.route('/insert_movie', methods=['POST'])
def insert_movie():
movie_added = {'title': request.form.get('title')}
{'imdb.rating': request.form.get('imdb.rating')}
{'tomato.rating': request.form.get('tomato.rating')}
{'year': request.form.get('year')}
{'runtime': request.form.get('runtime')}
{'actors': request.form.get('actors')}
{'director': request.form.get('director')}
{'plot': request.form.get('plot')}
mongo.db.movie_information.insert_one(movie_added)
return redirect(url_for('get_movies'))
Try putting all of the fields into a single object (see below). That way, when you insert one movie, that movie contains all of the fields from the one object that you sent.
movie_added = {'title': request.form.get('title'),
'imdb.rating': request.form.get('imdb.rating'),
'tomato.rating': request.form.get('tomato.rating'),
'year': request.form.get('year'),
'runtime': request.form.get('runtime'),
'actors': request.form.get('actors'),
'director': request.form.get('director'),
'plot': request.form.get('plot')}
mongo.db.movie_information.insert_one(movie_added)
return redirect(url_for('get_movies'))`
# this function clears text from fields.
def clear_text(self, field):
switcher = {
'company': self.company_name_textbox_id,
'email': self.email_textbox_id,
'website': self.website_textbox_id,
'phone': self.phone_textbox_id,
}
switcher.get(self.driver.find_element_by_id(field).clear(), "Invalid field provided")
def test03_existing_company_validation(self):
company = CompanyPage(self.driver)
company.clear_text('company')
clear_text is not working. Am I doing it right? How to fix it?
Seems like your logic is going in the wrong order. You should probably be passing field to your switcher dictionary and then passing the value from that to find_element_by_id.
self.driver.find_element_by_id(switcher[field]).clear()
I have a very simple dictionary with some data on it:
some_data= {'totalsForAllResults': {'ga:sessions': '11'}, 'profileInfo': {'internalWebPropertyId': '104132673', 'accountId': '67836206', 'profileName': 'My New Cool Site', 'webPropertyId': 'UA-677293506-1', 'profileId': '108628346', 'tableId': 'ga:108372846'},
on my views I have:
sessions = some_data['totalsForAllResults']['ga:sessions']
account_id = some_data['profileInfo']['accountId']
property_id = some_data['profileInfo']['internalWebPropertyId']
property_name = some_data['profileInfo']['profileName']
print(sessions,account_id,property_id,property_name)
return render(request, 'ga_app/report.html', {'sessions':sessions},
{'account_id':account_id},
{'property_id':property_id},
{'property_name':property_name},)
The variables get printed perfectly on my shell, however django doesn't want to pass them to the templates, I keep getting TypeError: unhashable type: 'dict' but I'm sending variables to the template not a dictionary. Why this happens?
Change this:
return render(request, 'ga_app/report.html', {'sessions':sessions},
{'account_id':account_id},
{'property_id':property_id},
{'property_name':property_name},)
to this:
return render(request, 'ga_app/report.html', {'sessions': sessions,
'account_id': account_id,
'property_id':property_id,
'property_name':property_name}
)
You have to pass one dict as the context. You are passing 4 of them!
I have a fairly basic CRUDMixin
class CRUDMixin(object):
""" create, read, update and delete methods for SQLAlchemy """
id = db.Column(db.Integer, primary_key=True)
#property
def columns(self):
return [ c.name for c in self.__table__.columns ]
def read(self):
""" return json of this current model """
return dict([ (c, getattr(self, c)) for c in self.columns ])
# ...
For something like an Article class which will subclass this, it might have a relationship with another class, like so:
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
The only real problem is that it will not return any user details in the json. Ideally, the json should look like this:
{
'id': 1234,
'title': 'this is an article',
'body': 'Many words go here. Many shall be unread. Roman Proverb.',
'author': {
'id': 14
'name': 'Thor',
'joined': October 1st, 1994
}
}
As it is right now, it will just give author_id: 14.
Can I detect if a column is a relationship and load it as json as well in this way?
You have to setup the entire relation by adding something like
author = db.relationship("Author") # I assume that you have an Author model
Then to json your result you have differents way to handle relations.
Take a look at this 2 responses :
jsonify a SQLAlchemy result set in Flask
How to serialize SqlAlchemy result to JSON?
You can also take a look at flask-restful which provide a method/decorator (marshal_with) to marshal your results in a good way with nested object (relations).
http://flask-restful.readthedocs.org/en/latest/fields.html#advanced-nested-field