question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unable to query db inside factory ('Iterator' object has no attribute '_sa_instance_state')

See original GitHub issue

I got this factory:

class DepartmentFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = models.Department
        sqlalchemy_session = Session

    abbreviation = 'MATH'

    @factory.lazy_attribute
    def school(self):
        return factory.Iterator(Session.query(models.School).all())

And I get this error: AttributeError: 'Iterator' object has no attribute '_sa_instance_state'

I’ve checked and made sure that the query returns a list of School objects.

Issue Analytics

  • State:open
  • Created 6 years ago
  • Comments:11 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
fgblomqvistcommented, Feb 1, 2018

Turning it into a generator function fixed it, thanks for the extensive explanation. Will use that for now. Treating it differently (and wrapping it accordingly) depending on if it’s an SQLAlchemy one or not feels the most natural to me (aka. the user does not have to care), but that is surely your decision to make.

Thanks for the in-depth explanation about the lack of self, the more you know! 😄 It was a bit of an eye-sore both for me and my IDE so solved it this way:

def schools():
    yield from models.School.query.all()


class DepartmentFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = models.Department
        sqlalchemy_session = models.db.session

    abbreviation = factory.Iterator(['COEN', 'MATH', 'POLI', 'MECH'])
    name = 'Sample Department'
    school = factory.iterator(schools)

😜

1reaction
rbarroiscommented, Jan 31, 2018

Oh, thanks for the stack!

Indeed, the factory.Iterator / factory.iterator functions work best with a generator function. It should work with:

@factory.iterator
def school():
    yield from Session.query(models.School).all()

Let’s dive under the hood here: a generator function (anything containing yield) returns a special object, which will only execute the function’s code (up to the next yield statement) once next(x) is called on it.

Django’s querysets are built upon generators, and work natively; however, it seems that SQLAlchemy’s querysets will evaluate directly; using a yield from x is equivalent to for i in x: yield i, and “wraps” the call in a generator.

This could be fixed either through better docs, or in the code; I’ll have to see which way feels most natural.

Regarding the lack of self:

There is some “dark magic” occurring in factory_boy: basically, the engine will collect all attributes from your class definition, and store them in some internal structures for later use.

I use the self parameter to calls because it feels more natural, but that’s actually a trick 😉 When creating an object, a method of those definitions is called with a stub for the attributes of the object to be built. Once that stub is filled, its attributes are used as kwargs for the actual model.

Since an iterator cannot be tuned for the object being built (whereas a lazy_attribute is designed for that!), there is no self parameter.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SQLAlchemy AttributeError: 'Query' object has no attribute ...
What I want basically is to create the objects I need to retrieve from the database to complete the data needed for a...
Read more >
Using a named iterator in an SQLJ application - IBM Db2 11.1
You declare any result set iterator using an iterator declaration clause. This causes an iterator class to be created that has the same...
Read more >
Iterate a Cursor in mongosh — MongoDB Manual
The db.collection.find() method returns a cursor. To access the documents, you need to iterate the cursor. However, in mongosh , if the returned...
Read more >
Multi-Row Query Results--SQLJ Iterators
A SQLJ iterator object is an instantiation of such a specifically declared iterator class, with a fixed number of columns of predefined type....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found