Preserve model structure when get dicts from SelectQuery
See original GitHub issueI have three models:
class User(Base):
name = CharField(null=False)
photo = BlobField()
email = CharField(unique=True, null=False)
password = CharField(null=False)
website = CharField(unique=True, null=False)
role = CharField(null=False, default="user")
reason = TextField(null=True)
state = CharField(null=False, default="waiting")
created_at = DateTimeField(null=False, default=datetime.now())
class Channel(Base):
name = CharField(unique=True, null=False)
cost = DoubleField(null=False)
passback = CharField(null=False)
class Campaign(Base):
name = CharField(null=False)
user = ForeignKeyField(User, null=False)
channel = ForeignKeyField(Channel, null=False)
target = CharField(null=False)
reason = TextField(null=True)
description = TextField(null=True)
state = CharField(null=False, default="waiting")
created_at = DateTimeField(null=False, default=datetime.now())
If a made a simple query I get the campaigns that I want, joining User and Channel models:
qs = Box(request.args, default_box=True)
page = int(qs.page[0])
state = qs.state[0]
query = (Campaign
.select(Campaign, User, Channel)
.join(User, on=(Campaign.user == User.id))
.join(Channel, on=(Campaign.channel == Channel.id))
.where(Campaign.state == state)
.order_by(Campaign.name)
.paginate(page, 10))
At this point I can simple iterate the query and get the data of joined models:
for cursor in query:
print(cursor.user.website) # http://johndoe.com
However, I need to return the query results in JSON, so, I did this (if I try to return the raw SelectQuery I get an “maximum recursion level reached” from ujson):
return json(query.dicts())
And the result is this:
[
{
"id": 5,
"name": "Computers and technology",
"user": 3,
"channel": 5,
"target": "http://janedoe.com",
"reason": null,
"description": "This is a campaign for my homepage",
"state": "active",
"created_at": 1494099722,
"photo": "/avatars/jane-doe.jpg",
"email": "jane.doe.68@mailna.in",
"password": "$2y$10$p/BuVFoKi9F9SVOc2yJzA.CM6n88xHhMBipNShp4skv9.WBbYxgQ2",
"website": "http://janedoe.com",
"role": "USER",
"cost": 0.04,
"passback": "https://pcmag.com"
}
]
All fields are mixed and, obviously, duplicated keys (name property of User
and Channel
are removed). This is not the expected result. Obviously, I can make a for loop to create a dict for each result and for model properties use model_to_dict
:
# convert a select query to a dicts array
campaigns = []
for row in query:
campaign = {}
campaign["name"] = row.name
campaign["target"] = row.target
campaign["user"] = model_to_dict(row.user)
campaign["channel"] = model_to_dict(row.channel)
campaign["description"] = row.description
campaign["reason"] = row.reason
campaign["state"] = row.state
campaign["created_at"] = row.created_at
campaigns.append(campaign)
But this means extra code and I like to keep things simple. So, the question is: exists some way to preserve the model structure when I convert the SelectQuery
to dicts?
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:6 (4 by maintainers)
Top GitHub Comments
Just one hint: you need to call
switch()
here:Secondly, why not try using the
model_to_dict
helper? I don’t see why it would be more code or why you’d need to explicitly create the dictionary:This is all very clearly documented, in my opinion: http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#model_to_dict
Please let me know if you found the docs confusing.