DRF Django - 制作可路由的反向外键关系数据
DRF Django - make routable reverse foreign key relationship data
我有以下型号
# filename - stocks.models
class Stock(models.Model):
ticker = models.CharField(max_length=10, unique=True, primary_key=True)
exchange = models.CharField(default="", max_length=10)
name = models.CharField(default="", max_length=255)
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)
class Meta:
verbose_name = "stock"
verbose_name_plural = "stocks"
ordering = ["ticker"]
# filename - prices.models
from viewflow.fields import CompositeKey
class StockPrice(models.Model):
id = CompositeKey(columns=["ticker_id", "date"])
ticker = models.ForeignKey(
"stocks.Stock", on_delete=models.CASCADE, related_name="stocks"
)
date = models.DateTimeField(default=now)
open = models.FloatField()
high = models.FloatField()
low = models.FloatField()
close = models.FloatField()
adj_close = models.FloatField()
volume = models.FloatField()
以下浏览量
class StockViewSet(viewsets.ModelViewSet):
queryset = Stock.objects.all()
queryset = queryset.prefetch_related("stocks")
serializer_class = StockSerializer
lookup_url_kwarg = "ticker"
lookup_field = "ticker__iexact"
# override create method to include many=True
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(
data=request.data, many=isinstance(request.data, list)
)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
)
#filename prices.views
class StockPriceViewSet(viewsets.ModelViewSet):
queryset = StockPrice.objects.all()
serializer_class = StockPriceSerializer
和以下路由器
router = routers.SimpleRouter()
router.register(r"stocks", stock_views.StockViewSet, basename="stocks")
stockprice_router = routers.NestedSimpleRouter(router, r"stocks", lookup="stocks")
stockprice_router.register(r"price", price_views.StockPriceViewSet)
urlpatterns = [
path("", include(router.urls)),
path("", include(stockprice_router))
]
路由器来自drf-nested-routers
。我如何设置一个 url 例如 localhost:8000/stocks/appl/price/
来显示反向外键数据 ( models.StockPrice
) 专门针对该股票 aapl.
目前,当我访问 localhost:8000/stocks/appl/price
时,我可以同时查看所有股票价格。
在这种情况下,重写 get_queryset
以根据选定的股票代码筛选出嵌套视图集将处理的对象,因此:
class StockPriceViewSet(viewsets.ModelViewSet):
queryset = StockPrice.objects.all()
serializer_class = StockPriceSerializer
def get_queryset(self):
queryset = super().get_queryset()
ticker = self.kwargs.get('stocks_ticker')
if ticker:
queryset = queryset.filter(ticker__ticker=ticker)
return queryset
以上是如果StockPriceViewSet
可以作为非嵌套viewset。但是,如果 StockPriceViewSet
仅嵌套在 StockViewSet
上:
class StockPriceViewSet(viewsets.ModelViewSet):
serializer_class = StockPriceSerializer
def get_queryset(self):
return StockPrice.objects.filter(ticker__ticker=self.kwargs['stocks_ticker'])
我有以下型号
# filename - stocks.models
class Stock(models.Model):
ticker = models.CharField(max_length=10, unique=True, primary_key=True)
exchange = models.CharField(default="", max_length=10)
name = models.CharField(default="", max_length=255)
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)
class Meta:
verbose_name = "stock"
verbose_name_plural = "stocks"
ordering = ["ticker"]
# filename - prices.models
from viewflow.fields import CompositeKey
class StockPrice(models.Model):
id = CompositeKey(columns=["ticker_id", "date"])
ticker = models.ForeignKey(
"stocks.Stock", on_delete=models.CASCADE, related_name="stocks"
)
date = models.DateTimeField(default=now)
open = models.FloatField()
high = models.FloatField()
low = models.FloatField()
close = models.FloatField()
adj_close = models.FloatField()
volume = models.FloatField()
以下浏览量
class StockViewSet(viewsets.ModelViewSet):
queryset = Stock.objects.all()
queryset = queryset.prefetch_related("stocks")
serializer_class = StockSerializer
lookup_url_kwarg = "ticker"
lookup_field = "ticker__iexact"
# override create method to include many=True
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(
data=request.data, many=isinstance(request.data, list)
)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
)
#filename prices.views
class StockPriceViewSet(viewsets.ModelViewSet):
queryset = StockPrice.objects.all()
serializer_class = StockPriceSerializer
和以下路由器
router = routers.SimpleRouter()
router.register(r"stocks", stock_views.StockViewSet, basename="stocks")
stockprice_router = routers.NestedSimpleRouter(router, r"stocks", lookup="stocks")
stockprice_router.register(r"price", price_views.StockPriceViewSet)
urlpatterns = [
path("", include(router.urls)),
path("", include(stockprice_router))
]
路由器来自drf-nested-routers
。我如何设置一个 url 例如 localhost:8000/stocks/appl/price/
来显示反向外键数据 ( models.StockPrice
) 专门针对该股票 aapl.
目前,当我访问 localhost:8000/stocks/appl/price
时,我可以同时查看所有股票价格。
在这种情况下,重写 get_queryset
以根据选定的股票代码筛选出嵌套视图集将处理的对象,因此:
class StockPriceViewSet(viewsets.ModelViewSet):
queryset = StockPrice.objects.all()
serializer_class = StockPriceSerializer
def get_queryset(self):
queryset = super().get_queryset()
ticker = self.kwargs.get('stocks_ticker')
if ticker:
queryset = queryset.filter(ticker__ticker=ticker)
return queryset
以上是如果StockPriceViewSet
可以作为非嵌套viewset。但是,如果 StockPriceViewSet
仅嵌套在 StockViewSet
上:
class StockPriceViewSet(viewsets.ModelViewSet):
serializer_class = StockPriceSerializer
def get_queryset(self):
return StockPrice.objects.filter(ticker__ticker=self.kwargs['stocks_ticker'])