flask many to many join as done by prefetch_related from django

2024/10/10 18:27:56

I have following Group and Contact model in flask with Sql Alchemy ORM

group_contact = db.Table('group_contact',db.Column('group_id', db.Integer, db.ForeignKey('group.id')),db.Column('contact_id', db.Integer, db.ForeignKey('contact.id')),db.PrimaryKeyConstraint('group_id', 'contact_id')
)class Group(db.Model):id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(100))class Contact(db.Model):id = db.Column(db.Integer, primary_key=True)phone = db.Column(db.String(15), nullable=False, unique=True)groups = db.relationship("Group", secondary=group_contact, backref='contacts')

Now I need to query Contact with groups:

contacts = Contact.query.join(Group, Contact.groups).all()
for contact in contacts:print(contact.groups)

Here the problem is number of SQL query increases as number of contact increases when I execute above code.

Django ORM has prefetch_related() with queryset which does the following according to django docs.

prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related.

Now I am trying to do the same thing with Sql Alchemy by the following code:

contacts = Contact.query.all()     
contact_groups = group_contact.query.join(Group
).filter(group_contact.contact_id.in_([item.id for item in contacts]))

But this gives me this error:

AttributeError: 'Table' object has no attribute 'query'

How can I get prefetch_related like feature from django with SqlAlchemy?

Answer

You want to tell SQLAlchemy to eagerly load related objects by using a relationship loading technique. SQLAlchemy can be told to load the groups together with the contacts in a single query.

For just this one query, you can add joinedload() option (it is available via the Flask-SQLAlchemy db object):

contacts = Contact.query.options(db.joinedload(Contact.groups)).all()

This pre-loads the Contact.groups attribute on each matched contact:

for contact in contacts:# no new query issued to fetch groups, the data for the groups# is already availableprint(contact.groups)

The query executed looks like this:

SELECT contact.id AS contact_id,contact.phone AS contact_phone,group_1.id AS group_1_id,group_1.name AS group_1_name
FROM contact 
LEFT OUTER JOIN (group_contact AS group_contact_1JOIN "group" AS group_1 ON group_1.id = group_contact_1.group_id
) ON contact.id = group_contact_1.contact_id

You can also set a default loading strategy for the relationship on the model; to always eagerly load groups, use lazy='joined' on the relationship:

class Contact(db.Model):# ...groups = db.relationship("Group", secondary=group_contact, backref='contacts',lazy='joined')
https://en.xdnf.cn/q/69861.html

Related Q&A

Django model inheritance - only want instances of parent class in a query

Lets say I have 2 models, one being the parent of another. How can I query all Places that arent restaurants in Django? Place.objects.all() would include all restaurants right? I want to exclude the …

Perfom python unit tests via a web interface

Is it possible to perform unittest tests via a web interface...and if so how?EDIT: For now I want the results...for the tests I want them to be automated...possibly every time I make a change to the …

Limit on number of HDF5 Datasets

Using h5py to create a hdf5-file with many datasets, I encounter a massive Speed drop after ca. 2,88 mio datasets. What is the reason for this?I assume that the limit of the tree structure for the dat…

Object level cascading permission in Django

Projects such as Django-guardian and django-permissions enables you to have object level permissions. However, if two objects are related to each other by a parent-child relationship, is there any way …

How do I find out eigenvectors corresponding to a particular eigenvalue of a matrix?

How do I find out eigenvectors corresponding to a particular eigenvalue? I have a stochastic matrix(P), one of the eigenvalues of which is 1. I need to find the eigenvector corresponding to the eigen…

How to install my custom Python package with its custom dependencies?

I would like to find a way to install my own python package which depends on other custom python packages. I followed this guide to create my own python packages: https://python-packaging.readthedocs.i…

How to call a function only Once in Python [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.Want to improve this question? Add details and clarify the problem by editing this post.Closed 8 years ago.The com…

Generating Compound Pie, or Pie of Pie Charts

Below is an example of a compound pie chart, also known as a pie of pie chart drawn using Excel. Is it possible to create a figure like this using python?

GitPython : git push - set upstream

Im using GitPython to clone a master branch and do a checkout of a feature branch, I do my local updates, commit and push back to git. The code snippet looks like below, Note : my branch name is featur…

How to access multi-level index in pandas data frame?

I would like to call those row with same index.so this is the example data frame, arrays = [np.array([bar, bar, baz, baz, foo, foo, qux, qux]), np.array([one, two, one, two, one, two, one, two])]df = p…