Django Rest Framework - повторное использование моделей logi c при десериализации ответов в python клиенте - PullRequest
0 голосов
/ 05 февраля 2020

При разработке REST API с использованием django и django rest Framework мне кажется, что в самом конце этой цепочки отсутствует шаг, , особенно если вы разрабатываете python клиент этого API :

  • определить модель ваших ресурсов в django
  • использовать сериализаторы DRF для отправки вашего ресурса по HTTP
  • пропущено: deserialize ваш ресурс обратно в python модель

Позвольте мне привести простой пример. Я объявляю следующую django модель с небольшим количеством бизнес-логики c:

class Numberplate(models.Model):
    number = models.CharField(max_length=128)
    country_code = models.CharField(max_length=3)

    def __repr__(self):
        return f"{self.number} ({self.country_code})"

DRF является очень мощным, когда речь идет о построении API вокруг этой модели. Однако, если я вызову этот API из python клиента, мне кажется, что лучшим ответом от этого API будет простой json без всех логик c, которые я мог бы написать в своей модели ( в этом случае, метод __repr__), и мне придется перемещаться по нему как таковой.

Продолжая мой пример, вот разница с надлежащим десериализатором и без него:

# the best we can do without rewriting code:
>> print(api.get(id=3))
{"numberplate": "123ABC", "country_code": "BE"}

# instead of re-using my __repr__, which would be ideal:
>> print(api.get(id=3))
123ABC (BE)

Есть ли чистый способ остаться DRY и написать логи c только один раз?

Я подумал о паре вариантов, которые, на мой взгляд, не являются удовлетворительными:

  • написать django -model-agnosti c Класс номерного знака и сделать вашу модель класс наследует как от models.Model, так и от этого класса
  • импортирует ваши django модели в ваш клиент ( как этот )

1 Ответ

0 голосов
/ 05 февраля 2020

Один вариант для вас будет использовать SerializerMethodField

class NumberplateSerializer(serializers.ModelSerializer):
    display = serializers.SerializerMethodField()

    class Meta:
        model = Nameplate
        fields = [..., 'display']

    def get_display(self, obj):
        return str(obj)
        # Or you can move your business logic here directly.
        # return f"{obj.number} ({obj.country_code})"

Теперь вы должны иметь:

>> print(api.get(id=3))
{"numberplate": "123ABC", "country_code": "BE", "display": "123ABC (BE)"}
...