marshmallow-jsonapi icon indicating copy to clipboard operation
marshmallow-jsonapi copied to clipboard

should flask.Schema.check_relationships honor data_key?

Open femto113 opened this issue 5 years ago • 0 comments

This problem just came up for me. I've got models that represent a person, and the person can have one or more "tickets", and each ticket may have an associated "pass" (think like going to a convention where the pass is the thing around your neck, the ticket is a more abstract thing you buy). Python veterans will immediately spot the problem: pass is a reserved word. Simplified code:

from marshmallow_jsonapi.flask import Relationship, Schema

class Person(Schema):
    ... other person fields ...
   tickets = Relationship(many=True, schema=Ticket, ...)

class Ticket(Schema):
  ... other ticket fields ...
  # because it's a reserved word, this field is named pass_ but we set the data_key so it shows up as pass
   pass_ = Relationship(schema=Pass, data_key='pass')

class Pass(Schema):
   ... pass fields ... 

The problem comes when trying to include the pass relationship, e.g. Person(include_data=['tickets.pass']) generates an error

marshmallow_jsonapi/schema.py, line 78, in __init__
   self.check_relations(self.include_data)", 
marshmallow_jsonapi/schema.py, line 117, in check_relations
   field.schema.check_relations(fields[1:])
marshmallow_jsonapi/schema.py, line 105, in check_relations
   raise ValueError(f'Unknown field "{local_field}"')
ValueError: Unknown field "pass"

This happens because this code looks in fields and pass isn't there (in fields it's named pass_)

    local_field = fields[0]
    if local_field not in self.fields:
        raise ValueError(f'Unknown field "{local_field}"')

Replacing that first line with

    local_field = next((n for n, f in self.fields.items() if f.data_key == fields[0]), fields[0])

seems to work--that just says use a field whose data_key matches the value from the include (if there is one). I'm guessing the vast majority of the time the field and the data_key are the same so this doesn't matter, but shouldn't includes always use the data_key since that's the only name the rest of the world knows the relationship by?

femto113 avatar Jul 28 '20 23:07 femto113