添加关联表后,我在使用架构序列化我的
Joke
数据时遇到问题。
这是我的模型,它允许用户输入笑话以及用于对笑话进行分类的标签:
class Joke(db.Model):
id = db.Column(db.Integer, primary_key=True)
joke_name = db.Column(db.String(40), nullable=False)
joke = db.Column(db.String(5000), nullable=False)
joke_owner = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
joke_category = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=True)
joke_created = db.Column(db.DateTime, nullable=True)
joke_edited = db.Column(db.DateTime, nullable=True)
tags = db.relationship('JokeTag', secondary=tag_joke, backref=db.backref('jokes', lazy='dynamic'), lazy='dynamic',
primaryjoin=tag_joke.c.joke_id==id,
secondaryjoin=tag_joke.c.joketag_id==JokeTag.id)
class JokeTag(db.Model):
id = db.Column(db.Integer, primary_key=True)
tag = db.Column(db.String(25), nullable=False)
tag_owner = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
这是我的关联表,以多对多的方式连接两者:
tag_joke = db.Table('tag_joke',
db.Column('joke_id', db.Integer, db.ForeignKey('joke.id')),
db.Column('joketag_id', db.Integer, db.ForeignKey('joke_tag.id'))
)
我正在尝试使用以下模式序列化数据:
class TagJokeSchema(ma.Schema):
class Meta:
fields = ('joke_id', 'joketag_id')
class JokeSchema(ma.Schema):
class Meta:
fields = ('id', 'joke_name', 'joke', 'joke_owner', 'joke_category', 'joke_created', 'joke_edited', 'tags')
tags=ma.Nested(TagJokeSchema, many=True)
我在架构上做了一些错误的事情,因为当我尝试用这个序列化数据时:
allnotes = Joke.query.filter_by(joke_owner=1).all()
result = jokes_schema.dump(allnotes)
我得到这个类型错误:
TypeError: Object of type AppenderBaseQuery is not JSON serializable
当我尝试从 python 命令行访问笑话和标签时,我能够访问笑话和相应的标签。尽管当我尝试打印一个笑话时,它看起来确实有点疯狂:
Joke('35','No reason','Finance people get buff for no reason. Just to work on Excel spreadsheets.','1','55', None, None, SELECT joke_tag.id AS joke_tag_id, joke_tag.tag AS joke_tag_tag, joke_tag.tag_owner AS joke_tag_tag_owner
FROM joke_tag, tag_joke
WHERE tag_joke.joke_id = %s AND tag_joke.joketag_id = joke_tag.id)
我希望能获得更干净的打印效果,如果有的话,标签嵌套在其中。
编辑@Greg0ry: allnotes 的打印输出如下所示:
[Joke('25','Test Joke','Knock, Knock, Whos There, test joke','1','55', None, None, SELECT joke_tag.id AS joke_tag_id, joke_tag.tag AS joke_tag_tag, joke_tag.tag_owner AS joke_tag_tag_owner FROM joke_tag, tag_joke WHERE tag_joke.joke_id = %s AND tag_joke.joketag_id = joke_tag.id), Joke('35','No reason','Finance people get buff for no reason. Just to work on Excel spreadsheets.','1','55', None, None, SELECT joke_tag.id AS joke_tag_id, joke_tag.tag AS joke_tag_tag, joke_tag.tag_owner AS joke_tag_tag_owner FROM joke_tag, tag_joke WHERE tag_joke.joke_id = %s AND tag_joke.joketag_id = joke_tag.id)]
我的
Joke
课程中也有这个解释打印输出的内容,我从我相信的 YouTube 教程中得到了这个(Corey Shafer):
def __repr__(self):
return f"Joke('{self.id}','{self.joke_name}','{self.joke}','{self.joke_owner}','{self.joke_category}', {self.joke_created}, {self.joke_edited}, {self.tags})"
就 db.Model 而言,我可能不明白你在寻找什么,但我有这个:
app = Flask(__name__)
db = SQLAlchemy(app)
希望有一种方法可以指导我更多地了解您正在寻找的内容?
如果我通过做事来寻找特定的笑话
jokequery = Joke.query.filter_by(joke_owner=1, id=595).first()
我明白了
Joke('595','test joke','knock knock whos there test joke','1','475', None, None, SELECT joke_tag.id AS joke_tag_id, joke_tag.tag AS joke_tag_tag, joke_tag.tag_owner AS joke_tag_tag_owner
FROM joke_tag, tag_joke
WHERE tag_joke.joke_id = %s AND tag_joke.joketag_id = joke_tag.id)
显然最后一部分看起来很糟糕。这是因为
tags
是 AppenderBaseQuery
但是如果我运行这个:
jokequery.tags.all()
输出看起来很棒,并且是一个可 JSON 序列化的列表:
[JokeTag('45', 'stackoverflow', '1')]
但是我该如何设置才能发送要序列化的列表而不是查询?
问题是关系上的
lazy='dynamic'
设置
...将为所有读取操作返回一个预先配置的查询对象...
我们可以删除此设置(也可以替换旧的
backref
):
# Some columns removed for brevity and readability.
class JokeTag(db.Model):
id = db.Column(db.Integer, primary_key=True)
tag = db.Column(db.String(25), nullable=False)
tag_owner = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
jokes = db.relationship('Joke', secondary='tag_joke', back_populates='tags')
class Joke(db.Model):
id = db.Column(db.Integer, primary_key=True)
joke_name = db.Column(db.String(40), nullable=False)
joke = db.Column(db.String(5000), nullable=False)
joke_owner = db.Column(
db.Integer, db.ForeignKey('user.id'), nullable=False
)
tags = db.relationship(
'JokeTag',
secondary=tag_joke,
lazy='dynamic',
back_populates='jokes'
)
如果您希望保留
lazy='dynamic'
设置,您可以对序列化输出进行后处理以获取查询结果:
...
class JokeSchema(ma.Schema):
class Meta:
fields = (
'id',
'joke_name',
'joke',
'joke_owner',
'joke_category',
'joke_created',
'joke_edited',
'tags',
)
tags = ma.fields.Nested(TagJokeSchema, many=True)
# Assuming ma in the question is Marshmallow
@ma.post_dump
def dump_tags(self, obj, **kw):
obj['tags'] = [t.name for t in obj['tags'].all()]
return obj