flask-rest-jsonapi icon indicating copy to clipboard operation
flask-rest-jsonapi copied to clipboard

Many to Many relationship

Open soulbreak opened this issue 6 years ago • 3 comments
trafficstars

Hello,

As reported in issue https://github.com/miLibris/flask-rest-jsonapi/issues/110 I tested the example, but the solution is not complete (Resource part and Url routing are missing) Is it possible to share an example ? Thank you.

soulbreak avatar Jan 25 '19 19:01 soulbreak

There is no need to create a table with a specific ID for that relationship

from flask_sqlalchemy import SQLAlchemy
from marshmallow_jsonapi import fields
from marshmallow_jsonapi.flask import Schema, Relationship
from flask_rest_jsonapi.resource import ResourceList, ResourceDetail, ResourceRelationship

db = SQLAlchemy()

# Create model
person_computer = db.Table('person_computer',
                           person_id=db.Column(db.BigInteger, db.ForeignKey('person.person_id')),
                           computer_id=db.Column(db.BigInteger, db.ForeignKey('computer.computer_id'))
                           )


# Create model
class Person(db.Model):
    __tablename__ = 'person'

    person_id = db.Column('person_id', db.BigInteger, primary_key=True)
    name = db.Column(db.String)

    computers = db.relationship("Computer", secondary='person_computer', back_populates="persons")


# Create model
class Computer(db.Model):
    __tablename__ = 'computer'

    computer_id = db.Column('computer_id', db.BigInteger, primary_key=True)
    serial = db.Column(db.String)

    persons = db.relationship("Person", secondary='person_computer', back_populates="computers")


# Create schema
class PersonSchema(Schema):
    class Meta:
        type_ = 'person'
        self_view = 'person_detail'
        self_view_kwargs = {'id': '<id>'}
        self_view_many = 'person_list'

    id = fields.Int(attribute="person_id")
    person_id = fields.Integer(as_string=True, dump_only=True)
    serial = fields.Str()

    computers = Relationship(self_view='person_computers',
                           self_view_kwargs={'id': '<person_id>'},
                           related_view='computer_list',
                           related_view_kwargs={'id': '<person_id>'},
                           many=True,
                           schema='ComputerSchema',
                           type_='computer')


# Create schema
class ComputerSchema(Schema):
    class Meta:
        type_ = 'computer'
        self_view = 'computer_detail'
        self_view_kwargs = {'id': '<id>'}
        self_view_many = 'computer_list'

    id = fields.Int(attribute="computer_id")
    computer_id = fields.Integer(as_string=True, dump_only=True)
    name = fields.Str()

    persons = Relationship(self_view='computer_persons',
                             self_view_kwargs={'id': '<computer_id>'},
                             related_view='person_list',
                             related_view_kwargs={'id': '<computer_id>'},
                             many=True,
                             schema='PersonSchema',
                             type_='person')

The resources you develop must be the ones you need. But basically reading the documentation you would have one for PersonDetail, PersonList, ComputerDetail, ComputerList and you can choose to have PersonRelationship or ComputerRelationship or both to handle relationship between Person and Computer.

ttecles avatar May 13 '19 08:05 ttecles

Hi ttecles,

I'm a little bit confused regarding to your code snippet. Is it right to give the ComputerSchema an attribute computers and the PersonSchema an attribute persons?

From my intuition it should be the other way round (but as I wrote, I'm confused at the moment).

I'm also a bit confused regarding to the Relationships in this case. What I would like to have would be the possibility to insert or delete the relationship via something like this:

POST /persons/<personId>/relationships/computers/<computerId> DELETE /persons/<personId>/relationships/computers/<computerId>

However the documentation is really sparse for a usecase like this (and adjustments on relationship resources in general). Could you give a pointer for that?

nbrinckm avatar May 27 '20 15:05 nbrinckm

Hi nbrinckm,

You are right, actually I see that is the quickstart. If you check the whole quickstart, just copying from that you have that relationship URI with the specified methods: https://flask-rest-jsonapi.readthedocs.io/en/latest/quickstart.html

ttecles avatar Jun 01 '20 08:06 ttecles