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

django rest framework using action decorator to add path to view financial statement in url

我需要以下 URLs 才能工作,其中 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" 装饰器实现 localhost:8000/stocks/<TICKER>/is/ 路径。

第三个URL已配置,但在浏览器中输入以下url时出现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

设置lookup_field = "ticker"

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

更新-1

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

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