# -*- coding: utf-8 -*-

from marshmallow import fields


def get_primary_column(model):
    columns = model.__mapper__.primary_key
    if len(columns) == 1:
        return columns[0]
    raise RuntimeError('Model {0!r} has multiple primary keys'.format(model))


class Related(fields.Field):

    @property
    def model(self):
        return self.parent.opts.model

    @property
    def related_model(self):
        return getattr(self.model, self.attribute or self.name).class_

    @property
    def related_column(self):
        return get_primary_column(self.related_model)

    @property
    def session(self):
        return self.parent.opts.sqla_session

    def _serialize(self, value, attr, obj):
        return getattr(value, self.related_column.key, None)

    def _deserialize(self, value):
        return self.session.query(
            self.related_model
        ).filter(
            self.related_column == value
        ).one()

@@ -82,16 +82,187 @@
 model):%0A
+    %22%22%22Get primary key column for a SQLAlchemy model.%0A%0A    :param model: SQLAlchemy model class%0A    :raise: RuntimeError if model has multiple primary key columns%0A    %22%22%22%0A
     colu
@@ -456,16 +456,215 @@
 .Field):
+%0A    %22%22%22Related data represented by a SQLAlchemy %60relationship%60. Must be attached%0A    to a :class:%60Schema%60 class whose options includes a SQLAlchemy %60model%60, such%0A    as :class:%60ModelSchema%60.%0A    %22%22%22
 %0A%0A    @p

Document related field.