Skip to content

Commit 506ddb5

Browse files
committed
readme and fix rewrite value
1 parent e521cae commit 506ddb5

File tree

5 files changed

+198
-19
lines changed

5 files changed

+198
-19
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,5 @@ dmypy.json
143143
cython_debug/
144144

145145
# End of https://www.toptal.com/developers/gitignore/api/python
146+
147+
debug.py

README.md

Lines changed: 171 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,185 @@
1-
# nested-multi-dimentional-parser
1+
# Nested-multipart-parser
22

3-
Parser for nested data in multipart form
3+
Parser for nested data in multipart form, you can use it anyways, and you have a django rest framework integration
4+
5+
# Installation
6+
7+
```bash
8+
pip install nested-multipart-parser
9+
```
410

511
# Usage
612

13+
## What is doing
14+
15+
the parser take the request data and transform to dictionary
16+
17+
exemple:
18+
719
```python
8-
from nested_multipart_parser import parser
9-
...
20+
# input
21+
{
22+
'title': 'title',
23+
'date': "time",
24+
'simple_object[my_key]': 'title'
25+
'simple_object[my_list][0]': True
26+
'langs[0][id]': 666,
27+
'langs[0][title]': 'title',
28+
'langs[0][description]': 'description',
29+
'langs[0][language]': "language",
30+
'langs[1][id]': 4566,
31+
'langs[1][title]': 'title1',
32+
'langs[1][description]': 'description1',
33+
'langs[1][language]': "language1"
34+
}
1035

11-
class YourViewSet(viewsets.ViewSet):
12-
parser_classes = (NestedMultipartParser,)
36+
# results are:
37+
{
38+
'title': 'title',
39+
'date': "time",
40+
'simple_object': {
41+
'my_key': 'title',
42+
'my_list': [
43+
True
44+
]
45+
},
46+
'langs': [
47+
{
48+
'id': 666,
49+
'title': 'title',
50+
'description': 'description',
51+
'language': 'language'
52+
},
53+
{
54+
'id': 4566,
55+
'title': 'title1',
56+
'description': 'description1',
57+
'language': 'language1'
58+
}
59+
]
60+
}
1361
```
1462

15-
To enable JSON and multipart
63+
## How is work
64+
65+
for this working perfectly you need to follow this rules:
66+
67+
- a first key need to be set ex: 'title[0]' or 'title', in both the first key is 'title'
68+
- each sub key need to enclose by brackets "[--your-key--]"
69+
- if sub key are a full number, is converted to list
70+
- if sub key is Not a number is converted to dictionary
71+
- the key can't be rewite
72+
ex:
1673

1774
```python
18-
from drf_nested_field_multipart import NestedMultipartParser
19-
from rest_framework.parsers import JSONParser
20-
from rest_framework import viewsets
75+
data = {
76+
'title[0]': 'my-value'
77+
}
78+
# output
79+
output = {
80+
'title': [
81+
'my-value'
82+
]
83+
}
2184

22-
class YourViewSet(viewsets.ViewSet):
23-
parser_classes = (JSONParser, NestedMultipartParser)
85+
# invalid key
86+
data = {
87+
'title[688]': 'my-value'
88+
}
89+
# ERROR , you set a number is upper thans actual list
90+
91+
92+
# wrong format
93+
data = {
94+
'title[0]]]': 'my-value',
95+
'title[0': 'my-value',
96+
'title[': 'my-value',
97+
'title[]': 'my-value',
98+
'[]': 'my-value',
99+
}
100+
101+
data = {
102+
'title': 42,
103+
'title[object]': 42
104+
}
105+
# Error , title as alerady set by primitive value (int, boolean or string)
106+
107+
# many element in list
108+
data = {
109+
'title[0]': 'my-value',
110+
'title[1]': 'my-second-value'
111+
}
112+
# output
113+
output = {
114+
'title': [
115+
'my-value',
116+
'my-second-value'
117+
]
118+
}
119+
120+
# converted to object
121+
data = {
122+
'title[key0]': 'my-value',
123+
'title[key7]': 'my-second-value'
124+
}
125+
# output
126+
output = {
127+
'title': {
128+
'key0': 'my-value',
129+
'key7': 'my-second-value'
130+
}
131+
}
132+
133+
# you have no limit for chained key
134+
data = {
135+
'the[0][chained][key][0][are][awesome][0][0]': 'im here !!'
136+
}
137+
# output
138+
output: {
139+
'the': [
140+
{
141+
'chained':{
142+
'key': [
143+
{
144+
'are': {
145+
'awesome':
146+
[
147+
[
148+
'im here !!'
149+
]
150+
]
151+
}
152+
}
153+
]
154+
}
155+
}
156+
]
157+
}
24158
```
25159

26-
# Installation
160+
# How to use it
161+
162+
## for every framwork
27163

28-
`pip install drf-nested-field-multipart`
164+
```python
165+
from nested_multipart_parser import NestedParser
166+
167+
def my_view():
168+
parser = NestedParser(data)
169+
if parser.is_valid():
170+
validate_data = parser.validate_data
171+
...
172+
else:
173+
print(parser.errors)
174+
175+
```
176+
177+
## for django rest framwork
178+
179+
```python
180+
from nested_multipart_parser.drf import DrfNestedParser
181+
...
182+
183+
class YourViewSet(viewsets.ViewSet):
184+
parser_classes = (DrfNestedParser,)
185+
```

nested_multipart_parser/parser.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,20 @@ def split_key(self, key):
2727
return results
2828

2929
def set_type(self, dtc, key, value, full_keys):
30-
if key.isdigit():
30+
if isinstance(dtc, list):
3131
key = int(key)
3232
if len(dtc) < key:
33-
raise Exception(
33+
raise ValueError(
3434
f"key \"{full_keys}\" is upper than actual list")
3535
if len(dtc) == key:
3636
dtc.append(value)
3737
return key
38-
elif key not in dtc:
39-
dtc[key] = value
38+
elif isinstance(dtc, dict):
39+
if key not in dtc:
40+
dtc[key] = value
41+
else:
42+
raise ValueError(
43+
f"invalid rewrite key from \"{full_keys}\" to \"{dtc}\"")
4044
return key
4145

4246
def construct(self, data):

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
setuptools.setup(
88
name="nested-multipart-parser",
9-
version="0.0.2",
9+
version="0.0.3",
1010
author="Example Author",
1111
license='MIT',
1212
author_email='[email protected]',

tests/test_parser.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,19 @@ def test_real(self):
279279
]
280280
}
281281
self.assertDictEqual(parser.validate_data, expected)
282+
283+
def test_parser_rewrite_key_list(self):
284+
data = {
285+
'title': 'lalal',
286+
'title[0]': 'lalal',
287+
}
288+
parser = NestedParser(data)
289+
self.assertFalse(parser.is_valid())
290+
291+
def test_parser_rewrite_key_boject(self):
292+
data = {
293+
'title': 'lalal',
294+
'title[object]': 'lalal',
295+
}
296+
parser = NestedParser(data)
297+
self.assertFalse(parser.is_valid())

0 commit comments

Comments
 (0)