2017-03-19 1 views
4

Je crée une API Flask à l'aide de modèles SQLAlchemy. Je ne veux pas définir un schéma pour chaque modèle que je l'ai, je ne veux pas le faire à chaque fois:Comment générer dynamiquement des schémas de guimauve pour les modèles SQLAlchemy

class EntrySchema(ma.ModelSchema): 
    class Meta: 
     model = Entry 

Je voudrais chaque modèle d'avoir un schéma, il peut facilement se vider . Création d'un schéma par défaut et le réglage de la Schema.Meta.model ne fonctionne pas:

class Entry(db.Model): 
    __tablename__ = 'entries' 

    id = db.Column(db.Integer, primary_key=True) 
    started_at = db.Column(db.DateTime) 
    ended_at = db.Column(db.DateTime) 
    description = db.Column(db.Text()) 

    def __init__(self, data): 
     for key in data: 
      setattr(self, key, data[key]) 

     self.Schema = Schema 
     self.Schema.Meta.model = self.__class__ 

    def dump(self): 
     schema = self.Schema() 
     result = schema.dump(self) 
     return result 


class Schema(ma.ModelSchema): 
    class Meta: 
     pass 

Pourquoi un schéma générique avec le modèle différent d'un écrasé de schéma avec le modèle déclaré?

Répondre

4

Vous pouvez créer un décorateur de classe qui ajoute la Schema à vos modèles:

def add_schema(cls): 
    class Schema(ma.ModelSchema): 
     class Meta: 
      model = cls 
    cls.Schema = Schema 
    return cls 

puis

@add_schema 
class Entry(db.Model): 
    ... 

Le schéma sera disponible en tant que l'attribut class Entry.Schema.

La raison pour laquelle votre tentative initiale échoue est que les classes de guimauve Schema sont construits à l'aide d'un custom metaclass, qui contrôle l'espace de noms créé à partir de l'exécution du corps de la classe et does its thing. Lorsque vous modifiez la classe déjà construite, il est trop tard.

Si vous n'êtes pas familier avec les métaclasses en Python, lisez à ce sujet dans le language reference. Ils sont un outil qui permet de grandes choses et une grande mauvaise utilisation.

0

Le marshmallow recipes prescrit quelques options alternatives pour lancer des options de schéma courantes dans une classe de base. Voici un exemple rapide directement à partir de la documentation:

# myproject/schemas.py 

from marshmallow_sqlalchemy import ModelSchema 

from .db import Session 

class BaseSchema(ModelSchema): 
    class Meta: 
     sqla_session = Session 

puis étendre le schéma de base:

# myproject/users/schemas.py 

from ..schemas import BaseSchema 
from .models import User 

class UserSchema(BaseSchema): 

    # Inherit BaseSchema's options 
    class Meta(BaseSchema.Meta): 
     model = User 

L'avantage de cette approche est que vous pouvez ajouter plus de/sérialisation à des modèles spécifiques

Plus d'exemples et de recettes sur les documents liés