Как сериализовать отдельный набор запросов в django rest framework? - PullRequest
0 голосов
/ 17 октября 2019

У меня есть модель, которая обрабатывает итальянские ставки НДС. Существует три типа тарифа: «Ординария», «Ридотта», «Минимум». Каждый тип тарифа может хранить несколько значений в зависимости от даты. Например, текущая ставка для обычного НДС составляет 22% и была установлена ​​1 октября 2013 года, но ставки менялись со временем, и мне нужно сохранять изменения и извлекать три ставки в соответствии с определенной датой.

Модель для описания ставок называется AliquoteIVA. Я использую собственный менеджер, чтобы получить текущие тарифы на сегодняшний день или указав конкретную дату:

class AliquoteIVAManager(models.Manager):
    def current(self, data):
        return self.filter(data__lte=data) \
                    .order_by('descrizione', '-data') \
                    .distinct('descrizione')


class AliquoteIVA(models.Model):
    """ Modello delle aliquote IVA """
    data = models.DateField(
        blank = False,
    )

    descrizione = models.CharField(
        blank = False,
        max_length = 1,
        default = IVA.IVA_ORDINARIA,
        choices = IVA.IVA_TIPOLOGIA_CHOICES,
    )

    aliquota = models.DecimalField(
        blank = False,
        null = False,
        default = '0',
        max_digits=19,
        decimal_places = 2,
        validators = [MinValueValidator(0.0)],
    )

    objects = AliquoteIVAManager()

    def __str__(self):
        str_aliquota = "{0:.2f}".format(self.aliquota).replace('.', ',')

        return "IVA {descrizione} al {aliquota}% in vigore dal {data}".format(
            descrizione=self.get_descrizione_display(),
            aliquota=str_aliquota,
            data=self.data
            )

    class Meta:
        ordering = ('-data', 'aliquota',)
        verbose_name = 'Aliquota IVA'
        verbose_name_plural = 'Aliquote IVA'

Я протестировал наборы запросов и все работает нормально:

AliquoteIVA.objects.all() будетreturn:

<QuerySet [
  <AliquoteIVA: IVA Ordinaria al 26,50% in vigore dal 2021-01-01>, 
  <AliquoteIVA: IVA Ridotta al 13,00% in vigore dal 2020-01-01>,
  <AliquoteIVA: IVA Ordinaria al 25,20% in vigore dal 2020-01-01>,
  <AliquoteIVA: IVA Minima al 4,00% in vigore dal 2013-10-01>,
  <AliquoteIVA: IVA Ridotta al 10,00% in vigore dal 2013-10-01>,
  <AliquoteIVA: IVA Ordinaria al 22,00% in vigore dal 2013-10-01>,
  <AliquoteIVA: IVA Ordinaria al 20,00% in vigore dal 1997-10-01>,
  <AliquoteIVA: IVA Ordinaria al 19,00% in vigore dal 1988-08-01>,
  <AliquoteIVA: IVA Ordinaria al 18,00% in vigore dal 1982-08-05>
]>

AliquoteIVA.objects.current('2019-10-17') вернет:

<QuerySet [
  <AliquoteIVA: IVA Minima al 4,00% in vigore dal 2013-10-01>,
  <AliquoteIVA: IVA Ordinaria al 22,00% in vigore dal 2013-10-01>,
  <AliquoteIVA: IVA Ridotta al 10,00% in vigore dal 2013-10-01>
]>

Все работает как положено, но мне нужно настроить сериализатор и некоторую конечную точку API для использования этих скоростей в клиенте.

Сериализатор для AliquoteIVA довольно прост:

class AliquoteIVASerializer(serializers.ModelSerializer):
    """
    Serializer per le aliquote IVA
    """
    class Meta:
        model = AliquoteIVA
        fields = '__all__'
        read_only_fields = [
            'id'
            ]

Я установил два вида:

  • , первый AliquoteIVAViewset предоставит конечные точки APIпо курсу CURD.
  • последний CurrentAliquoteIVAView просто предоставит общий список API только для чтения для отображения текущих тарифов.
class AliquoteIVAViewset(viewsets.ModelViewSet):
    """
    API endpoint per le aliquote IVA
    """

    queryset = AliquoteIVA.objects.all()
    serializer_class = AliquoteIVASerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    filter_backends = [filters.SearchFilter]
    search_fields = ['descrizione']


class CurrentAliquoteIVAView(generics.ListAPIView):
    """
    API endpoint per vedere le aliquote IVA correnti in data odierna
    o in base a una data specifica (Y-m-d)
    """

    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    filter_backends = [filters.SearchFilter]
    search_fields = ['descrizione']

    def get(self, request, data=None, format=None):
        qdata = data if data is not None else datetime.today()

        queryset = AliquoteIVA.objects.current(qdata)
        return Response(queryset)

Первый вид обрабатываетсямаршрутизатором в URL-адресах, второй явно указывается в URL-адресах и требует параметра data

router = routers.DefaultRouter()
router.register(r'aliquote/iva', views.AliquoteIVAViewset)


aliquote_iva_patterns = [
    path('', views.CurrentAliquoteIVAView.as_view()),
    path('<str:data>', views.CurrentAliquoteIVAView.as_view()),
]


urlpatterns = [
    path('aliquote/iva/corrente/', include(aliquote_iva_patterns)),
    path('', include(router.urls))
]

Первый вид (набор настроек) работает должным образом, но когда я пытаюсь достичь конечной точки APIчтобы показать список текущих ставок, django выдаст ошибку:

Exception Type: TypeError
Exception Value:    
Object of type 'AliquoteIVA' is not JSON serializable

Почему AliquoteIVA.objects.current('2019-10-17') не сериализуемый объект?

Как я могу сериализовать current набор запросов?

1 Ответ

1 голос
/ 17 октября 2019

Определив get, вы обошли все функции DRF. В частности, вы не вызываете сериализатор, который отвечает за преобразование объекта в сериализуемую форму.

Эта логика должна идти в get_queryset, а не get.

class CurrentAliquoteIVAView(generics.ListAPIView):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    filter_backends = [filters.SearchFilter]
    search_fields = ['descrizione']
    serializer_class = AliquoteIVASerializer

    def get_queryset(self):
        qdata = self.kwargs.get('data', datetime.today())
        queryset = AliquoteIVA.objects.current(qdata)
        return queryset
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...