scythargon
scythargon

Reputation: 3491

Flask-admin: How to do inline editing for manytomany relations?

I have two models

class Message(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    message_text = db.Column(db.Text, nullable=True)
    stickers = db.relationship('StickerMessageAssociation', back_populates='message')
    ...

and

class Sticker(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    file_id = db.Column(db.String(255), nullable=False)
    messages = db.relationship('StickerMessageAssociation', back_populates='sticker')
   ...

and an intermediate model to connect these two:

class StickerMessageAssociation(db.Model):
    __tablename__ = 'message_to_sticker'

    message_id = db.Column(db.Integer, db.ForeignKey('message.id'), primary_key=True)
    sticker_id = db.Column(db.Integer, db.ForeignKey('sticker.id'), primary_key=True)

    message = db.relationship('Message', back_populates='stickers')
    sticker = db.relationship('Sticker', back_populates='messages')

The problem arises when I try to enable support for assigning stickers to the messages in the flask-admin via inline model editing:

class InlineStickerModelForm(InlineFormAdmin):
    form_label = 'Stickers'

    def __init__(self):
        return super(InlineStickerModelForm, self).__init__(StickerMessageAssociation)


class MessageView(ModelView):
    ...
    inline_models = (..., InlineStickerModelForm())

When I add a sticker to a message in the admin panel, which looks like this: image

and try to save the page, I get the following error: image

Tried to hack my way around scaffold_inline_form_models and in a few other directions but no luck so far. Any suggestions would be very much appreciated. Thank you!

Upvotes: 3

Views: 1348

Answers (2)

scythargon
scythargon

Reputation: 3491

Okay, here is how I've solved it.

I've changed the relationship table to have a separate PK like this:

class StickerMessageAssociation(db.Model, HandyModel):
    __tablename__ = 'message_to_sticker'

    id = db.Column(db.Integer, primary_key=True)

    message_id = db.Column(db.Integer, db.ForeignKey('message.id'), nullable=False)
    sticker_id = db.Column(db.Integer, db.ForeignKey('sticker.id'), nullable=False)

    message = db.relationship('Message', back_populates='stickers')
    sticker = db.relationship('Sticker', back_populates='messages')

And added form_columns = ('id', 'sticker') definition to InlineStickerModelForm.

Upvotes: 2

gittert
gittert

Reputation: 1308

I think the table you created as intermediate model is not correct. I do many-to-many relations as follows, I changed the code to your situation:

sticker_message_asociation = db.Table(
    'sticker_message_asociation',
    db.Column(db.Integer, db.ForeignKey('message.id')),
    db.Column(db.Integer, db.ForeignKey('sticker.id'))
    )

Upvotes: 1

Related Questions