File: serializers.py

package info (click to toggle)
python-django-ordered-model 3.7.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 592 kB
  • sloc: python: 2,139; sh: 38; makefile: 11
file content (103 lines) | stat: -rw-r--r-- 3,409 bytes parent folder | download | duplicates (2)
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