Using marshmallow
2.18.0, flask-marshmallow
0.9.0.
I'm building a system which handles a series of questions and answers. The next question displayed depends on the answer to the previous question. To model this I have two Answer
foreign keys pointing to Question
.
The problem is that AnswerSchema
doesn't show the hyperlink or any data at all for next_question
, which I'm trying to pull in using flask-marshmallow's HyperlinkRelated function. However it does work for question
(the question that the answer is answering).
$ http localhost:5000/answers/1/
{
"answer": "Great",
"id": 1,
"question": "/questions/1/", *# Works, but where is next_question?*
}
If it's relevant, I do see next_question
in answer_schema._declared_fields
, but not in answer_schema.dump(answer).data
.
By the way, Nested
works well in the other direction when I query for a Question
:
$ http localhost:5000/questions/1/
{
"answers": [
{
"answer": "Great",
"id": 1,
"question": "/questions/1/",
},
{
"answer": "More than great",
"id": 2,
"question": "/questions/1/",
}
],
"id": 1,
"question": "How are you doing today?",
}
Anyway, I'm not sure if HyperlinkRelated
is the right way to go about this, but if it's not, I don't see what to do. I'd really appreciate understanding what is the correct approach (should I be using Nested
in the other direction as well?!?!), and why i.e. what I've missed in the docs.
Here's related (I removed what I could to keep it short, it's a mix from different files):
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from sqlalchemy_mixins import AllFeaturesMixin
db = SQLAlchemy()
ma = Marshmallow()
class GenericMixin:
id = db.Column(db.Integer, primary_key=True)
class BaseModel(db.Model, AllFeaturesMixin, GenericMixin):
__abstract__ = True
BaseModel.set_session(db.session)
from flask_classful import FlaskView
from webargs import fields
from webargs.flaskparser import use_kwargs
from .resources.user import User, User
class Question(BaseModel):
question = db.Column(db.String(128), unique=True, nullable=False)
answers = db.relationship('Answer', backref='question',
foreign_keys='Answer.question_id')
class QuestionSchema(ma.ModelSchema):
class Meta:
model = Question
answers = ma.Nested(AnswerSchema, many=True, strict=True)
question_schema = QuestionSchema(strict=True)
class QuestionsView(FlaskView):
def get(self, id):
question = Question.query.get_or_404(id)
return question_schema.jsonify(question)
class Answer(BaseModel):
answer = db.Column(db.String(128), unique=True, nullable=False)
question_id = db.Column(db.Integer,
db.ForeignKey('question.id'),
nullable=False)
next_question_id = db.Column(db.Integer,
db.ForeignKey('question.id'),
nullable=True)
class AnswerSchema(ma.ModelSchema):
class Meta:
model = Answer
question = ma.HyperlinkRelated('QuestionsView:get')
# HELP! How do I get this to return the link to the next question?
next_question = ma.HyperlinkRelated('QuestionsView:get')
answer_schema = AnswerSchema(strict=True)
class AnswersView(FlaskView):
def get(self, id):
answer = Answer.query.get_or_404(id)
return answer_schema.jsonify(answer)
Thanks to lftl on Reddit for providing the answer. I simply had to add the backref to Question
.
class Question(BaseModel):
question = db.Column(db.String(128), unique=True, nullable=False)
answers = db.relationship(
"Answer", backref="question", foreign_keys="Answer.question_id"
)
next_question = db.relationship(
"Answer", backref="next_question", foreign_keys="Answer.next_question_id"
)
The Reddit link contains other useful discussion. I found that HyperlinkRelated
doesn't support foreign key nulls, but there's an open PR, and the monkey patch works great.