Use of Marshmallow without repetition

According to Marshmallow's official docs, it is recommended to declare a schema, and then have a separate class that receives the loaded data, for example:

class UserSchema(Schema): name = fields.Str() email = fields.Email() created_at = fields.DateTime() @post_load def make_user(self, data): return User(**data) 

However, the User class will look something like this:

 class User: def __init__(name, email, created_at): self.name = name self.email = email self.created_at = created_at 

This seems to be repeated unnecessarily, and I really don't like to write attribute names three more times. However, I like IDE autocomplete and static type checking on well-defined structures.

So, is there any best practice for loading serialized data according to the Marshmallow Pattern without defining another class?

+9
source share
2 answers

For Python vanilla classes, there is no ready-made method for defining a class for a schema without repeating field names.

If you use SQLAlchemy, for example, you can define the schema directly from the model using marshmallow_sqlalchemy.ModelSchema :

 from marshmallow_sqlalchemy import ModelSchema from my_alchemy_models import User class UserSchema(ModelSchema): class Meta: model = User 

The same goes for flask-sqlalchemy, which uses flask_marshmallow.sqla.ModelSchema .

In the case of Python vanilla classes, you can define the fields once and use it for both the schema and the model / class:

 USER_FIELDS = ('name', 'email', 'created_at') class User: def __init__(self, name, email, created_at): for field in USER_FIELDS: setattr(self, field, locals()[field]) class UserSchema(Schema): class Meta: fields = USER_FIELDS @post_load def make_user(self, data): return User(**data) 
+4
source

You will have to create two classes, but the good news is that in most cases you do not have to enter attribute names several times. One thing I discovered if you use Flask, SQLAlchemy, and Marshmallow is that if you define some validation attributes in your Column definition, the Marshmallow schema will automatically select them and the validations provided in them. For instance:

 import (your-database-object-from-flask-init) as db import (your-marshmallow-object-from-flask-init) as val class User(db.Model): name = db.Column(db.String(length=40), nullable=False) email = db.Column(db.String(length=100)) created_at = db.Column(db.DateTime) class UserSchema(val.ModelSchema): class Meta: model = User 

In this example, if you take a data dictionary and put it in UserSchema (). Load (data), you will see errors if in this example the name does not exist or the name is longer than 40 characters, or the email address is longer than 100 characters. Any user checks, except that you still have to code in your circuit.

This also works if you created a model class as an extension of another model class, transferring its attributes. For example, if you want each class to create / modify information, you can put these attributes in the parent class of the model, and the child will inherit them along with the verification parameters. Marshmallow does not allow your parent model to have a schema, so I have no information about user checks there.

I know that you probably already completed your project, but I hope this helps other developers who are faced with this.

Corresponding pips list: Flask (1.0.2) flask-marshmallow (0.9.0) Flask-SQLAlchemy (2.3.2) marshmallow (2.18.0) marshmallow-sqlalchemy (0.15.0) SQLAlchemy (1.2.16)

+2
source

Source: https://habr.com/ru/post/1271079/


All Articles