django rest框架使用动作装饰器在url中添加查看财务报表的路径

Posted

技术标签:

【中文标题】django rest框架使用动作装饰器在url中添加查看财务报表的路径【英文标题】:django rest framework using action decorator to add path to view financial statement in url 【发布时间】:2020-12-09 18:21:58 【问题描述】:

我需要以下 URL 才能工作,其中ticker 代表股票代码(例如 AAPL 或 AMZN),is 代表income_statement。

localhost:8000/stocks/ localhost:8000/stocks/<TICKER>/ localhost:8000/stocks/<TICKER>/is/

在下面的views.py文件中,我使用了一个视图集,它和路由器自动配置了上面的前两个url,对于第三个url,我使用带有methods=['get']url_path="is"的动作装饰器来实现@ 987654326@路径。

第三个网址已配置,但在浏览器中输入以下网址时出现ticker 的关键错误:localhost:8000/stocks/AAPL/is/

我在这里做错了什么,我相信错误出在views.py get_income_statement 函数中?

models.py

class Stock(models.Model):

    id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    ticker = models.CharField(max_length=10, unique=True, primary_key=True)
    slug = models.SlugField(default="", editable=False)

    def save(self, *args, **kwargs):
        value = self.ticker
        self.slug = slugify(value, allow_unicode=True)
        super().save(*args, **kwargs)

    def __str__(self):
        return self.ticker

    class Meta:
        verbose_name = "stock"
        verbose_name_plural = "stocks"
        ordering = ["ticker"]

class IncomeStatement(models.Model):
    ticker = models.ForeignKey(
        Stock, on_delete=models.CASCADE, related_name="income_statements"
    )

    date = models.DateField(default=datetime.date.today)
    PERIODICITY_CHOICES = [("ANNUAL", "ANNUAL"), ("QUARTERLY", "QUARTERLY")]
    periodicity = models.CharField(
        max_length=10, choices=PERIODICITY_CHOICES, default="annually"
    )
    net_income_continuous_operations = models.DecimalField(
        max_digits=20, decimal_places=2

views.py

class StockViewSet(viewsets.ModelViewSet):
    queryset = Stock.objects.all()
    serializer_class = StockSerializer
    # lookup_field = "slug"

    @action(detail=True, methods=["get"], url_path="is", url_name="is")
    def get_income_statement(self, request, *args, **kwargs):
        income_statement = self.queryset.get(ticker=kwargs["ticker"]).select_related(
            "income_statements"
        )
        serializer = IncomeStatementSerializer(data=income_statement)
        if serializer.is_valid():
            return Response(serializer.data)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

urls.py

router = DefaultRouter()
router.register(r"stocks", views.StockViewSet)
urlpatterns = router.urls

【问题讨论】:

是的,它们都可以正常工作 错误在views.py文件的get_income_statement函数中 做到了。 . .解决了一个错误现在我得到了回复"Invalid data. Expected a dictionary, but got RelatedManager." 有什么解决办法吗? 因此,您必须将income_statements 用作self.get_object().income_statements,而不是将您的序列化程序用作IncomeStatementSerializer(data=income_statements, many=True)请清理旧的 cmets 【参考方案1】:

设置lookup_field = "ticker"

class StockViewSet(viewsets.ModelViewSet):
    # rest of your code
    lookup_field = "ticker"

更新-1

class StockViewSet(viewsets.ModelViewSet):
    queryset = Stock.objects.all()
    serializer_class = StockSerializer
    lookup_field = "ticker"

    @action(detail=True, methods=["get"], url_path="is", url_name="is")
    def get_income_statement(self, request, *args, **kwargs):
        is_qs = IncomeStatement.objects.filter(ticker=self.get_object())
        serializer = IncomeStatementSerializer(is_qs, many=True)
        return Response(serializer.data)

【讨论】:

解决了原来的问题,现在我得到了错误'Stock' object has no attribute 'select_related' select_related 仅适用于 QuerySet 而不是对象 另外,我看不出您有任何理由需要致电select_related() 该错误表明您错误地定义了一个(或多个字段)。 url参数传递给kwargs

以上是关于django rest框架使用动作装饰器在url中添加查看财务报表的路径的主要内容,如果未能解决你的问题,请参考以下文章

用于覆盖 post 方法的 Django REST 框架自定义装饰器

使用 django-rest 框架中的 GET 方法将 url 作为参数传递?

在 django rest 框架中定义 searchFilter URL

django-rest-framework 序列化器在多个视图中的不同字段

如何在 Django REST 框架中使用事务?

Django REST 框架:使用 URL 中的 ID 发布到 URL