https://github.com/alexei/python-adapters
Adapters allow converting data from one structure to another
https://github.com/alexei/python-adapters
adapter-pattern python
Last synced: 11 months ago
JSON representation
Adapters allow converting data from one structure to another
- Host: GitHub
- URL: https://github.com/alexei/python-adapters
- Owner: alexei
- License: bsd-3-clause
- Created: 2017-04-02T17:43:41.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2022-06-09T09:46:48.000Z (over 3 years ago)
- Last Synced: 2025-03-18T08:21:41.161Z (11 months ago)
- Topics: adapter-pattern, python
- Language: Python
- Homepage: https://pypi.python.org/pypi/python-adapters
- Size: 42 KB
- Stars: 10
- Watchers: 6
- Forks: 2
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Adapters
[](https://travis-ci.org/alexei/python-adapters)
Adapters allow converting data from one structure to another.
The adapters work very similar to `Serializers` in Django REST framework. They are not tied with Django nor DRF in any way, instead they provide a generic way of transforming an object to another.
The are intended to be used when working with 3rd party APIs and as View-Models.
## Example
Suppose you're dealing with an API that returns a profile in the following format:
{
"first_name": "Alexandra",
"last_name": "Johnson",
"dob": "2/27/1985",
"address_street": ["71 Boat Lane"],
"address_zip": "EH45 0ZQ",
"address_city": "Alderton",
"address_country": "GB"
}
But your local models are a little different:
class Address(object):
def __init__(self, **kwargs):
self.line1 = kwargs.get('line1', None)
self.line2 = kwargs.get('line2', None)
self.postal_code = kwargs.get('postal_code', None)
self.city = kwargs.get('city', None)
self.region = kwargs.get('region', None)
self.country = kwargs.get('country', None)
class Profile(object):
def __init__(self, **kwargs):
self.first_name = kwargs.get('first_name', None)
self.last_name = kwargs.get('last_name', None)
self.birthday = kwargs.get('birthday', None)
self.address = kwargs.get('address', None)
How do you create local instances from the result returned by the API? Enter adapters:
import adapters
class AddressAdapter(adapters.Adapter):
class Meta(object):
model = Address
line1 = adapters.CharField(source='address_street.0')
line2 = adapters.CharField(source='address_street.1', default='')
postal_code = adapters.CharField(source='address_zip')
city = adapters.CharField(source='address_city')
region = adapters.CharField(source='address_region', default='')
country = adapters.CharField(source='address_country')
class ProfileAdapter(adapters.Adapter):
class Meta(object):
model = Profile
first_name = adapters.CharField()
first_name = adapters.CharField()
birthday = adapters.DateField(source='dob')
address = AddressAdapter(source='*')
ProfileAdapter().adapt(remote_data)
## Declaring adapters
Declaring an adapter is as simple as inheriting from `adapters.Adapter`.
The `data` argument can be omitted and passed to the `.adapt()` method. See [Adapting data](#adapting-data) below.
The `instance` argument is optional and it allows converting to an existing instance i.e. instead of creating a new one.
### Meta options
The `Meta.model` field specifies the type of the end result. Defaults to `dict` and as such the data is converted to a dictionary.
### Adapting data
To convert data from one format to another, call the `Adapter.adapt()` method. It accepts an optional `data` argument which refers to the data to be converted.
## Fields
Each field accepts the following arguments:
* `source` refers to the attribute that will be used to populate the field; the default is to use the same name as the field;
The `source` argument can use dotted notation to traverse objects e.g. `profile.birthday`.
The value `*` can be used to indicate the adapter to pass the entire object to the field.
* `default` specifies the default value of the resulting field; if not set and the field is required, it will raise an error
* `required` indicates whether the field should be required or not; default is `True`
The following field types are available:
### AdapterMethodField
The field gets it's value by calling a method defined on the adapter class. It can be used to manipulate the data.
The `method_name` argument refers to the name of the method. It defaults to `get_`.
### BooleanField
Converts the result to a boolean value.
### CharField
A Unicode field.
### DateField
Parses the value into a `datetime.date` object.
### DateTimeField
Parses the value into a `datetime.datetime` object.
### DecimalField
Parses the value into a `Decimal` object.
### FloatField
A float field.
### IntField
An integer field.
### TimeField
Parses the value into a `datetime.time` object.
### VerbatimField
Copy the value as is.