У меня есть модель, которая обрабатывает итальянские ставки НДС. Существует три типа тарифа: «Ординария», «Ридотта», «Минимум». Каждый тип тарифа может хранить несколько значений в зависимости от даты. Например, текущая ставка для обычного НДС составляет 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
набор запросов?