在Django Rest Framework中,如何添加ManyToMany相关对象?

时间:2018-04-03 14:56:24

标签: django-rest-framework

这是我的代码:

模型

3

查看

@echo off
setlocal enableDelayedExpansion
:: random value
set ParId=123

:: get the last number of the previous value
set /a "temp0=%ParId% %% 10"

:: part of my array, just for the example
set AsciiNumTable[0]=0x30
set AsciiNumTable[1]=0x31
set AsciiNumTable[2]=0x32
set AsciiNumTable[3]=0x33

:: PART NOT WORKING
set ParIdByte0=!AsciiNumTable[%temp0%]!

echo --%ParIdByte0%--

串行器

class Recipe(models.Model):
  name = models.CharField(max_length=50, unique=True)
  ingredient = models.ManyToManyField(Ingredient)

class Ingredient(models.Model):
  name = models.CharField(max_length=50, unique=True)

我从以下Recipe对象开始:

class RecipeDetailAPIView(RetrieveUpdateDestroyAPIView):
  permission_classes = (IsAdminOrReadOnly,)
  serializer_class = RecipeSerializer
  queryset = Recipe.objects.all()

  def put(self, request, *args, **kwargs):
    return self.update(request, *args, **kwargs)

  def perform_update(self, serializer):
    serializer.save(updated_by_user=self.request.user)

现在,我试图通过将以下JSON对象更新到IngredientSerializer来更新该对象:

class IngredientSerializer(serializers.ModelSerializer):

    class Meta:
        model = Ingredient
        fields = [
      'id',
            'name',
        ]

class RecipeSerializer(serializers.ModelSerializer):
  ingredient = IngredientSerializer(many=True, read_only=False)

  class Meta:
    model = Recipe
    fields = [
      'id',
      'name',
      'ingredient',
    ]

我想要的是认识到与Potato的关系已经存在并跳过它,但是添加了与Mayo对象的关系。请注意,Mayo对象已存在于Ingredients中,但尚未绑定到Potato Salad对象。

实际发生的是Serializer尝试创建一个新的Ingredient对象并失败,因为"具有此名称的成分已经存在。"

我如何做到这一点?

1 个答案:

答案 0 :(得分:1)

DRF没有任何自动&#34;写&#34;嵌套序列化程序的行为,正是因为它不知道如何在您提到的场景中进行更新。因此,您需要在library(shiny) library(DT) library(dplyr) options(scipen = -1) options(digits = 3) # Define UI for application that draws a histogram ui <- fluidPage( # Application title titlePanel("Old Faithful Geyser Data"), # Sidebar with a slider input for number of bins sidebarLayout( sidebarPanel( ), # Show a plot of the generated distribution mainPanel( DTOutput("dt"), DTOutput("dt2") ) ) ) # Define server logic required to draw a histogram server <- function(input, output) { output$dt <- renderDT({cars/1000000}) output$dt2 <- renderDT({ mutate_all(cars/1000000, funs(signif(., digits = 1))) }) } # Run the application shinyApp(ui = ui, server = server) 中编写自己的update方法。

RecipeSerializer

相关DRF文档:

Saving Instances

Writable Nested Serializer

Updating nested serializers

<强>更新

如果名称字段中的唯一性约束的DRF验证失败,则应尝试删除该字段的验证器。

替代解决方案:仅将完整序列化程序用作只读字段

您可以将RecipeSerializer更改为以下内容:

class IngredientSerializer(serializers.ModelSerializer):
  def validate_name(self, value):
    # manually validate
    pass

  class Meta:
    model = Ingredient
    fields = ['id', 'name']
    extra_kwargs = {
        'name': {'validators': []}, # remove uniqueness validation
    }


class RecipeSerializer(serializers.ModelSerializer):
  ingredient = IngredientSerializer(many=True, read_only=False)

  def update(self, instance, validated_data):
    ingredients = validated_data.pop('ingredient')
    # ... logic to save ingredients for this recipe instance
    return instance

  class Meta:
    model = Recipe
    fields = ['id', 'name', 'ingredient']

就是这样。无需覆盖class RecipeSerializer(serializers.ModelSerializer): ingredient_details = IngredientSerializer(many=True, read_only=True, source='ingredient') class Meta: model = Recipe fields = ['id', 'name', 'ingredient', 'ingredient_details'] 或其他任何内容。获得食谱后,您将获得详细的表示,并且您可以在更新时使用成分ID。所以你的json在更新时会看起来像这样:

update