Skip to content
This repository has been archived by the owner on Aug 14, 2024. It is now read-only.

chrismaille/marshmallow-pynamodb

 
 

Repository files navigation

Welcome to Marshmallow-Pynamo-DB

PyPI Build PyPI - Python Version Code style: black pre-commit

PynamoDB integration with the Marshmallow (de)serialization library.

Installation

From PyPi:

  $ pip install marshmallow-pynamo-db

Versions

Declare your models

from pynamodb.models import Model
from pynamodb.attributes import UnicodeAttribute

class User(Model):
    class Meta:
        table_name = "user"
    email = UnicodeAttribute(null=True)
    first_name = UnicodeAttribute(range_key=True)
    last_name = UnicodeAttribute(hash_key=True)

Generate marshmallow schemas

from marshmallow_pynamodb import ModelSchema

class UserSchema(ModelSchema):
    class Meta:
        model = User

user_schema = UserSchema()

(De)serialize your data

user = User(last_name="Smith", first_name="John")

user_schema.dump(user)
# {u'first_name': u'John', u'last_name': u'Smith', u'email': None}

user_schema.load({"last_name": "Smith", "first_name": "John"})
# user<Smith>

pynamodb-attributes support

Currently we support the following custom attributes from pynamodb-attributes library:

  • IntegerAttribute – same as NumberAttribute but whose value is typed as int (rather than float)
  • UUIDAttribute - serializes a UUID Python object as a S type attribute (e.g. 'a8098c1a-f86e-11da-bd1a-00112444be1e')
  • UnicodeEnumAttribute - serializes a string-valued Enum into a Unicode (S-typed) attribute
  • IntegerEnumAttribute - serializes a integer-valued Enum into a Number (S-typed) attribute
import uuid
from enum import Enum

from pynamodb.attributes import UnicodeAttribute
from pynamodb.models import Model
from pynamodb_attributes import IntegerAttribute, UUIDAttribute, UnicodeEnumAttribute

from marshmallow_pynamodb import ModelSchema


class Gender(Enum):
    male = "male"
    female = "female"
    not_informed = "not_informed"


class People(Model):
    class Meta:
        table_name = "people"
    uuid = UUIDAttribute(hash_key=True)
    first_name = UnicodeAttribute()
    last_name = UnicodeAttribute()
    gender = UnicodeEnumAttribute(Gender)
    age = IntegerAttribute()


class PeopleSchema(ModelSchema):
    class Meta:
        model = People


people_schema = PeopleSchema()
payload = {
    "uuid": "064245dc0e5f415c95d3ba6b8f728ae4",
    "first_name": "John",
    "last_name": "Doe",
    "gender": Gender.male.value,
    "age": 43
}
people = people_schema.load(payload)
# people<064245dc-0e5f-415c-95d3-ba6b8f728ae4>
assert people.gender == Gender.male
assert people.uuid == uuid.UUID("064245dc0e5f415c95d3ba6b8f728ae4")

See more examples in tests.

Nested models? No problem

from marshmallow_pynamodb.schema import ModelSchema

from pynamodb.models import Model
from pynamodb.attributes import (
    ListAttribute,
    MapAttribute,
    NumberAttribute,
    UnicodeAttribute,
)

class Location(MapAttribute):
    latitude = NumberAttribute()
    longitude = NumberAttribute()
    name = UnicodeAttribute()


class Person(MapAttribute):
    firstName = UnicodeAttribute()
    lastName = UnicodeAttribute()
    age = NumberAttribute()


class OfficeEmployeeMap(MapAttribute):
    office_employee_id = NumberAttribute()
    person = Person()
    office_location = Location()


class Office(Model):
    class Meta:
        table_name = 'OfficeModel'

    office_id = NumberAttribute(hash_key=True)
    address = Location()
    employees = ListAttribute(of=OfficeEmployeeMap)


class OfficeSchema(ModelSchema):
    class Meta:
        model = Office

# noinspection PyTypeChecker
OfficeSchema().load(
    {
        'office_id': 789,
        'address': {
            'latitude': 6.98454,
            'longitude': 172.38832,
            'name': 'some_location'
        },
        'employees': [
            {
                'office_employee_id': 123,
                'person': {
                    'firstName': 'John',
                    'lastName': 'Smith',
                    'age': 45
                },
                'office_location': {
                    'latitude': -24.0853,
                    'longitude': 144.87660,
                    'name': 'other_location'
                }
            },
            {
                'office_employee_id': 456,
                'person': {
                    'firstName': 'Jane',
                    'lastName': 'Doe',
                    'age': 33
                },
                'office_location': {
                    'latitude': -20.57989,
                    'longitude': 92.30463,
                    'name': 'yal'
                }
            }
        ]
    }
)
# Office<789>

Using polyformed Models

# pip install pynamodb_attributes
import uuid
from pynamodb_attributes import UnicodeEnumAttribute, UUIDAttribute
from pynamodb.attributes import UnicodeAttribute, DiscriminatorAttribute
from pynamodb.models import Model
from marshmallow_pynamodb import ModelSchema
from enum import Enum

class MyStatus(Enum):
   CREATED = "CREATED"

class BaseDocument(Model):
  uuid = UUIDAttribute(default=uuid.uuid4)
  cls = DiscriminatorAttribute()

class MyDocument(BaseDocument, discriminator='my_document'):
  status = UnicodeEnumAttribute(MyStatus, default=MyStatus.CREATED)
  content = UnicodeAttribute()

class MyDocumentSchema(ModelSchema):
  class Meta:
    model = MyDocument

instance = MyDocumentSchema().load({"content": "foo"})
assert instance.content == "foo"
assert instance.uuid is not None

License

MIT licensed. See the bundled LICENSE file for more details.

Not working?

Dont panic. Get a towel and, please, open an issue.

About

PynamoDB integration with Marshmallow

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 98.8%
  • Makefile 1.2%