我有两个型号,目录和史诗:

class Catalog(models.Model):
    created_on = models.DateTimeField(auto_now_add=True)
    active = models.BooleanField(null=False, default=False)


class Epic(models.Model):
    name = models.CharField(max_length=128, null=False)
    slug = models.SlugField(null=False)
    catalog = models.ForeignKey(Catalog, null=False, on_delete=models.CASCADE)

我已经使用DRF为Catalog创建了CRUD视图集和序列化程序.现在我想为Epic创建CRUD视图集和序列化程序,以便像/catalogs/<int:catalog_pk>/epics/<int:pk>一样使用.我使用的是DRF嵌套路由:

router = routers.SimpleRouter()
router.register("catalog", CatalogViewSet)

catalog_router = routers.NestedSimpleRouter(router, "catalog", lookup="catalog")
catalog_router.register("epics", EpicsViewSet, basename="epics")

urlpatterns = router.urls + catalog_router.urls

以下是我对《史诗》的看法和序列化:

class EpicsViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
    serializer_class = EpicSerializer
    permission_classes = (IsAuthenticated, CatalogPermissions)

    def get_queryset(self):
        return Epic.objects.filter(catalog=self.kwargs["catalog_pk"])


class EpicSerializer(serializers.ModelSerializer):

    class Meta:
        model = Epic
        fields = "__all__"

我try 像这样运行创建终结点:使用EPIC数据发布/catalog/1/epics/,但我得到的错误是有效负载中缺少catalog字段.我希望这是从URL kwargs自动完成的.我希望它从kwargs中获取catalog_id,并将目录实例设置为序列化程序中新创建的Epic实例.

最直接的方法是覆盖序列化程序中的create函数,但我对此犹豫不决,我想知道是否有更"僵化"的方法来做到这一点.

推荐答案

您可以使用一个简单的Mixin来修补get_querysetperform_create方法:

class FilterCreateGetMixin:
    filter_field_name = None
    filter_kwarg_name = None

    def get_filter_dict(self):
        return {self.filter_field_name: self.kwargs[self.filter_kwarg_name]}

    def get_queryset(self, *args, **kwargs):
        return (
            super().get_queryset(*args, **kwargs).filter(**self.get_filter_dict())
        )

    def perform_create(self, serializer):
        serializer.save(**self.get_filter_dict())

然后,我们可以专门为该类别制作一个Mixin,例如:

class CategoryFilterMixin(FilterCreateGetMixin):
    filter_field_name = 'catalog'
    filter_kwarg_name = 'catalog_pk'

并在视图集/API视图中混合以下内容:

class EpicSerializer(serializers.ModelSerializer):
    class Meta:
        model = Epic
        exclude = ['catalog']


class EpicsViewSet(
    CategoryFilterMixin, mixins.CreateModelMixin, viewsets.GenericViewSet
):
    serializer_class = EpicSerializer
    permission_classes = (IsAuthenticated, CatalogPermissions)

这样做的好处是,我们可以很容易地将其混合到所有其他视图中,其中我们的路径中有category_pk.

Python相关问答推荐

决策树分类器的基础sklearn熵和log_loss标准是否有差异?

当pip为学校作业(job)安装sourcefender时,我没有收到匹配的分发错误.我已经try 过Python 3.8.10和3.10.11

Pandas 群内滚动总和

使用Beautiful Soup获取第二个srcset属性

用Python获取HTML Span类中的数据

如何修复使用turtle和tkinter制作的绘画应用程序的撤销功能

在上下文管理器中更改异常类型

如何用symy更新分段函数

根据网格和相机参数渲染深度

大Pandas 胚胎中产生组合

如何使用pandasDataFrames和scipy高度优化相关性计算

max_of_three使用First_select、second_select、

Python json.转储包含一些UTF-8字符的二元组,要么失败,要么转换它们.我希望编码字符按原样保留

如何获得每个组的时间戳差异?

我想一列Panadas的Rashrame,这是一个URL,我保存为CSV,可以直接点击

Pandas—在数据透视表中占总数的百分比

解决调用嵌入式函数的XSLT中表达式的语法移位/归约冲突

dask无groupby(ddf. agg([min,max])?''''

如何在两列上groupBy,并使用pyspark计算每个分组列的平均总价值

如何使用OpenGL使球体遵循Python中的八样路径?