使用DRF中的序列化器字段的子集反序列化POST请求 [英] Deserialize POST request with subset of serializer fields in DRF

查看:449
本文介绍了使用DRF中的序列化器字段的子集反序列化POST请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个非常简单的问题,但是找到了一些解决方案,并且不停地想知道预期的DRF方法是什么。

I'm having a rather simple problem, but found a few solutions and couldn't stop wondering what the intended DRF approach would be.

我有一个(简化的)模型和序列化器,如下所示:

I have a (simplified) model and serializer like this:

class CartProduct(models.Model):
    cart = models.ForeignKey('Cart', on_delete=models.CASCADE)
    product = models.ForeignKey('Product', on_delete=models.CASCADE)

class CartProductSerializer(serializers.HyperlinkedModelSerializer):
    id = serializers.ReadOnlyField()
    product = ProductSerializer()

    class Meta:
        model = CartProduct
        fields = ('id', 'url', 'product')

哪个会生成如下所示的GET响应:

Which produces a GET response like this:

"url": "http://localhost:8000/appUsers/1/cart/products/16/",
"id": 16,
"product": {
    "url": "http://localhost:8000/products/1/",
    "id": 1,
    "name": "Tomatoes",
},
"cart": "http://localhost:8000/carts/1/"

但是,现在创建新的CartProduct时,在默认情况下,我需要像上面的那样传递一个嵌套的产品字典,以根据POST请求创建/反序列化新的CartProduct。

However, when creating a new CartProduct now, in this default scenario I would need to pass a nested product dictionary like the one above to create / deserialize a new CartProduct from a POST request.

我想要发送的是带有主体的POST请求,仅使用主键或url来创建新的购物车产品,例如像这样:

What I would like instead is to send a POST request with a body using just primary keys or urls to create a new cart product, e.g. like this:

"product": 1,
"cart": 1

"product": "http://localhost:8000/products/1/"
"cart": "http://localhost:8000/carts/1/"

所以现在我想知道实现这一目标的最佳方法是什么?我想到了:

So now I was wondering what would be the best way to achieve this? I thought of:


  • 编写两个单独的序列化器(但我不喜欢这样的模型,几乎每个模型都有两个序列化器) )

  • 向每个序列化器添加其他字段,以确保嵌套/相关模型始终由url和/或id表示,并且仅使这些ID字段为必需

  • 重写验证/创建函数以使所需输入为有效格式

  • 重写ModelViewSet的create函数并在那里处理问题

  • Writing two separate serializers (but I don't like the idea of having two serializers for pretty much every model like this)
  • Adding additional fields to every serializer making sure that nested / related models are always represented by url and / or id and only making these ID fields required
  • Overriding the validation / create function in order to make the desired input a valid format
  • Overriding the ModelViewSet's create functions and dealing with the issue there

最适合处理此类案件的地方是什么?

What would be the most appropriate place for dealing with such a case?

推荐答案

我更喜欢使用以下方法,其中我有 2个序列化器字段用于1个模型字段(一个只读字段用于详细信息,一个id / url字段用于创建和更新):

I prefer to use the following approach where I have 2 serializer fields for 1 model field (one read only field for details and one id/url field for creates and updates):

class CartProductSerializer(serializers.HyperlinkedModelSerializer):
    product_detail = ProductSerializer(source='product', read_only=True) 

    class Meta:
        model = CartProduct
        fields = ('url', 'cart', 'product', 'product_detail')

请注意,这是假设 ProductSerializer 已在其他位置定义。而且我省略了id,因为我们并不是真的需要它,但是您仍然可以根据需要添加它。

Note that this assumes ProductSerializer is already defined elsewhere. And I'm omitting id because we don't really need it but you can still add it if you want.

这具有以下优点:


  • 您可以对所有CRUD操作使用相同的序列化器。

  • 您可以在GET上获取嵌套字段的详细信息,但可以为POST / PUT上的嵌套字段提供ID。

  • 您不必在视图中编写任何自定义逻辑即可解析等。-您可以坚持使用默认的通用视图功能,您可以立即使用

因此,在您的特定情况下,为获取的JSON将是:

So in your specific case, the JSON you'll get back for a GET will be:

{
  "url": "http://localhost:8000/appUsers/1/cart/products/16/",
  "product": "http://localhost:8000/products/1/"
  "product_detail": {
    "url": "http://localhost:8000/products/1/",
    "name": "Tomatoes",
  },
  "cart": "http://localhost:8000/carts/1/"
}

对于POST,您将继续ly需要发送:

And for POSTs you'll only need to send:

{
  "product": "http://localhost:8000/products/2/"
  "cart": "http://localhost:8000/carts/1/"
}

对于PUT,在上述JSON中包含 CartProduct 对象自己的 url

For PUTs, include the CartProduct object's own url in the above JSON.

这篇关于使用DRF中的序列化器字段的子集反序列化POST请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆