如何使用棉花糖序列化自定义sqlalchemy字段?

时间:2015-10-16 00:40:54

标签: python flask flask-sqlalchemy marshmallow

我刚开始一个名为flask_wiki的简单项目,我使用了一些烧瓶扩展,如下所示:

  • 烧瓶SQLAlchemy的
  • 合剂的RESTful
  • 棉花糖

好吧,我刚刚发现MarshMallow项目提供了一个名为' ModelSchema'的类,它从我的SQLAlchemy模型中读取所有字段并提供一个完全自动化的(de)序列化器。

在我的情况下,我创建了一个' GUID'与RDBM无关的字段并将其插入我的Sqlalchemy模型,如下所示:

echo $query;

GUIDField以这种方式实现:

from flask.ext.sqlalchemy import SQLAlchemy
from flask_wiki.backend.custom_fields import GUIDField

class Page(db.Model):
    """
    Implements the Page Model.
    """
    guid = db.Column(GUIDField, primary_key=True, default=uuid.uuid4)
    name = db.Column(db.String, nullable=False)
    raw_content = db.Column(db.Text)
    rendered_content = db.Column(db.Text)

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return self.name

创建测试对象的代码(通过混音器)正在运行;所有的guid都是正确生成和验证的。

考虑到这一点,刚刚创建了以下MarshMallow Serializer字段:

from sqlalchemy.types import TypeDecorator, CHAR
import uuid


class GUIDField(TypeDecorator):
    # Platform independent GUID Implementation that uses little endianess.
    impl = CHAR

    def load_dialect_impl(self, dialect):
        return dialect.type_descriptor(CHAR(32))

    def process_bind_param(self, value, dialect):
        if value is None:
            return value
        else:
            if isinstance(value, uuid.UUID):
                return value.bytes_le

    def process_result_value(self, value, dialect):
        if value is None:
            return value
        else:
            return uuid.UUID(bytes_le=value)

最后,我创建了SerializerClass:

from marshmallow import fields
import uuid


class GUIDSerializationField(fields.Field):
    def _serialize(self, value, attr, obj):
        if value is None:
            return value
        else:
            if isinstance(value, uuid.UUID):
                return str(value)
            else:
                return None

我尝试使用和不插入guid字段的最后一个代码,但在所有情况下都会发生以下错误:

from flask_wiki.backend.backend import marsh
from flask_wiki.backend.custom_serialization_fields import GUIDSerializationField
from flask_wiki.backend.models import Page
from marshmallow import fields


class PageSchema(marsh.ModelSchema):
    class Meta:
        model = Page

    guid = GUIDSerializationField()


page_schema = PageSchema()
pages_schema = PageSchema(many=True)

所以,我终于问:如何使用marshmallow序列化自定义sqlalchemy字段?

2 个答案:

答案 0 :(得分:7)

您需要创建自己的转换器。 尝试这样的事情:

import uuid
from flask_wiki.backend.models import Page
from flask_wiki.backend.backend import marsh
from marshmallow_sqlalchemy.convert import ModelConverter
from flask_wiki.backend.custom_fields import GUIDField
from marshmallow import fields


#Here you are overwriting the list of types of the SQLAlchemy, adding your custom type 
class GUIDConverter(ModelConverter):
    SQLA_TYPE_MAPPING = dict(
        list(ModelConverter.SQLA_TYPE_MAPPING.items()) + 
        [(GUIDField, fields.Str)] 
    )

class GUIDSerializationField(fields.Field):
    def _serialize(self, value, attr, obj):
        if value is None:
            return value
        else:
            if isinstance(value, uuid.UUID):
                return str(value)
            else:
                return None

class PageSchema(marsh.ModelSchema):
    class Meta:
        model = Page        
        model_converter = GUIDConverter #Tell to Marshmallow to use your custom converter for this model

    guid = GUIDSerializationField(attribute="guid")

您还可以查看this链接以获取帮助。 我希望它对我糟糕的英语有帮助和抱歉

答案 1 :(得分:2)

根据我在文档中阅读的内容,您可以在ModelSchema Meta class中指定一个model_converter属性。 ModelConverter class具有select * from posts left outer join votes on votes.votable_id = posts.id and votes.votable_type = 'Posts' and votes.user_id = 16 ---> (My user_id) where posts.user_id = 21 ---> (user_id i'm looking at) 属性,您可以在子类中覆盖该属性,以将自定义GUID字段添加到自动架构生成器检测到的类型中。

那就是说,我从未使用它,所以我不知道这是否有用。