Skip to content

Commit 0f93f54

Browse files
committed
Update README; close #30
1 parent 621efec commit 0f93f54

1 file changed

Lines changed: 143 additions & 1 deletion

File tree

README.md

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,143 @@
1-
# Adapter
1+
# Adapters
2+
3+
Adapters allow converting data from one structure to another.
4+
5+
The adapters work very similar to `Serializers` in Django REST framework. They are not tied with Django nor DRF in any way, instead they probide a generic way of transforming an object to another.
6+
7+
The are intended to be used when working with 3rd party APIs and as View-Models.
8+
9+
## Example
10+
11+
Suppose you're dealing with an API that returns a profile in the following format:
12+
13+
{
14+
"first_name": "Alexandra",
15+
"last_name": "Johnson",
16+
"dob": "2/27/1985",
17+
"address_street": ["71 Boat Lane"],
18+
"address_zip": "EH45 0ZQ",
19+
"address_city": "Alderton",
20+
"address_country": "GB"
21+
}
22+
23+
But your local models are a little different:
24+
25+
class Address(object):
26+
def __init__(self, **kwargs):
27+
self.line1 = kwargs.get('line1', None)
28+
self.line2 = kwargs.get('line2', None)
29+
self.postal_code = kwargs.get('postal_code', None)
30+
self.city = kwargs.get('city', None)
31+
self.region = kwargs.get('region', None)
32+
self.country = kwargs.get('country', None)
33+
34+
35+
class Profile(object):
36+
def __init__(self, **kwargs):
37+
self.first_name = kwargs.get('first_name', None)
38+
self.last_name = kwargs.get('last_name', None)
39+
self.birthday = kwargs.get('birthday', None)
40+
self.address = kwargs.get('address', None)
41+
42+
How do you create local instances from the result returned by the API? Enter adapters:
43+
44+
import adapters
45+
46+
47+
class AddressAdapter(adapters.Adapter):
48+
class Meta(object):
49+
model = Address
50+
51+
line1 = adapters.CharField(source='address_street.0')
52+
line2 = adapters.CharField(source='address_street.1', default='')
53+
postal_code = adapters.CharField(source='address_zip')
54+
city = adapters.CharField(source='address_city')
55+
region = adapters.CharField(source='address_region', default='')
56+
country = adapters.CharField(source='address_country')
57+
58+
59+
class ProfileAdapter(adapters.Adapter):
60+
class Meta(object):
61+
model = Profile
62+
63+
first_name = adapters.CharField()
64+
first_name = adapters.CharField()
65+
birthday = adapters.DateField(source='dob')
66+
address = AddressAdapter(source='*')
67+
68+
69+
ProfileAdapter().adapt(remote_data)
70+
71+
72+
## Declaring adapters
73+
74+
Declaring an adapter is as simply as inheriting from `adapters.Adapter`
75+
76+
The `data` argument can be omitted and passed to the `.adapt()` method. See [Adapting data](#adapting-data) below.
77+
78+
The `instance` argument is optional and it allows converting to an existing instance i.e. instead of creating a new one.
79+
80+
### Meta options
81+
82+
The `Meta.model` field specifies the type of the end result. Defaults to `dict` and as such the data is converted to a dictionary.
83+
84+
### Adapting data
85+
86+
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.
87+
88+
## Fields
89+
90+
Each field accepts the following arguments:
91+
92+
* `source` refers to the attribute that will be used to populate the field; the default is to use the same name as the field;
93+
94+
The `source` argument can use dotted notation to traverse objects e.g. `profile.birthday`.
95+
96+
The value `*` can be used to indicate the adapter to pass the entire object to the field.
97+
98+
* `default` specifies the default value of the resulting field; if not set and the field is required, it will raise an error
99+
* `required` indicates whether the field should be required or not; default is `True`
100+
101+
The following field types are available:
102+
103+
### AdapterMethodField
104+
105+
The field gets it's value by calling a method defined on the adapter class. It can be used to manipulate the data.
106+
107+
The `method_name` argument refers to the name of the method. It defaults to `get_<field_name>`.
108+
109+
### BooleanField
110+
111+
Converts the result to a boolean value.
112+
113+
### CharField
114+
115+
A Unicode field.
116+
117+
### DateField
118+
119+
Parses the value into a `datetime.date` object.
120+
121+
### DateTimeField
122+
123+
Parses the value into a `datetime.datetime` object.
124+
125+
### DecimalField
126+
127+
Parses the value into a `Decimal` object.
128+
129+
### FloatField
130+
131+
A float field.
132+
133+
### IntField
134+
135+
An integer field.
136+
137+
### TimeField
138+
139+
Parses the value into a `datetime.time` object.
140+
141+
### VerbatimField
142+
143+
Copy the value as is.

0 commit comments

Comments
 (0)