forked from django-ordered-model/django-ordered-model
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserializers.py
103 lines (76 loc) · 3.33 KB
/
serializers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from rest_framework import serializers, fields
class OrderedModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer to provide a serializer that can be update and create
objects in a specific order.
Typically a `models.PositiveIntegerField` field called `order` is used to
store the order of the Model objects. This field can be customized by setting
the `order_field_name` attribute on the Model class.
This serializer will move the object to the correct
order if the ordering field is passed in the validated data.
"""
def get_order_field(self):
"""
Return the field name for the ordering field.
If inheriting from `OrderedModelBase`, the `order_field_name` attribute
must be set on the Model class. If inheriting from `OrderedModel`, the
`order_field_name` attribute is not required, as the `OrderedModel`
has the `order_field_name` attribute defaulting to 'order'.
Returns:
str: The field name for the ordering field.
Raises:
AttributeError: If the `order_field_name` attribute is not set,
either on the Model class or on the serializer's Meta class.
"""
ModelClass = self.Meta.model # pylint: disable=no-member,invalid-name
order_field_name = getattr(ModelClass, "order_field_name")
if not order_field_name:
raise AttributeError(
"The `order_field_name` attribute must be set to use the "
"OrderedModelSerializer. Either inherit from OrderedModel "
"(to use the default `order` field) or inherit from "
"`OrderedModelBase` and set the `order_field_name` attribute "
"on the " + ModelClass.__name__ + " Model class."
)
return order_field_name
def get_fields(self):
# make sure that DRF considers the ordering field writable
order_field = self.get_order_field()
d = super().get_fields()
for name, field in d.items():
if name == order_field:
if field.read_only:
d[name] = fields.IntegerField()
return d
def update(self, instance, validated_data):
"""
Update the instance.
If the `order_field_name` attribute is passed in the validated data,
the instance will be moved to the specified order.
Returns:
Model: The updated instance.
"""
order = None
order_field = self.get_order_field()
if order_field in validated_data:
order = validated_data.pop(order_field)
instance = super().update(instance, validated_data)
if order is not None:
instance.to(order)
return instance
def create(self, validated_data):
"""
Create a new instance.
If the `order_field_name` attribute is passed in the validated data,
the instance will be created at the specified order.
Returns:
Model: The created instance.
"""
order = None
order_field = self.get_order_field()
if order_field in validated_data:
order = validated_data.pop(order_field)
instance = super().create(validated_data)
if order is not None:
instance.to(order)
return instance