You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST Framework:基于联合唯一约束的存在则更新序列化器

Alright, let's work through this. You've got a Run model with a unique constraint on (start_time, chamber), and you want a Django REST Framework serializer that will update an existing instance if that unique combination already exists, instead of throwing a validation error. Here's a clean way to implement this:

First, let's recap your Run model (plus a basic Chamber model assumption since you referenced it):

from django.db import models

class Chamber(models.Model):
    name = models.CharField(max_length=100, unique=True)  # Assuming your Chamber uses a unique name field

    def __str__(self):
        return self.name

class Run(models.Model):
    start_time = models.DateTimeField(db_index=True)
    end_time = models.DateTimeField()
    chamber = models.ForeignKey(Chamber, on_delete=models.CASCADE)
    
    class Meta:
        unique_together=(('start_time', 'chamber'),)

Now here's the serializer that handles the upsert (update or insert) behavior:

from rest_framework import serializers
from .models import Run, Chamber

class RunSerializer(serializers.ModelSerializer):
    # Convert the chamber name from your POST data to a valid Chamber instance
    chamber = serializers.SlugRelatedField(
        queryset=Chamber.objects.all(),
        slug_field='name'  # Replace this with your Chamber field that stores values like "My Test Chamber"
    )

    class Meta:
        model = Run
        fields = ['start_time', 'end_time', 'chamber']

    def create(self, validated_data):
        # Extract the fields that form your unique constraint
        unique_identifiers = {
            'start_time': validated_data['start_time'],
            'chamber': validated_data['chamber']
        }

        # Use Django's get_or_create to fetch existing run or create a new one
        run, created = Run.objects.get_or_create(
            **unique_identifiers,
            defaults=validated_data
        )

        # If the run already exists, update its fields (we'll update end_time here)
        if not created:
            # Update specific fields or loop through all validated data if needed
            run.end_time = validated_data['end_time']
            # Add more field updates here if you want to sync other values
            run.save()

        return run

How this works:

  • SlugRelatedField: This handles converting the chamber name from your POST data ("My Test Chamber") into a valid Chamber instance. It also automatically validates that the chamber exists in the database.
  • get_or_create: This Django ORM method checks for an existing Run with the start_time and chamber combination. If it exists, it returns the instance; if not, it creates a new one using the provided defaults data.
  • Update logic: When the instance already exists (created is False), we update the necessary fields (in this case end_time) and save the changes. You can expand this to update other fields by adding more run.field = validated_data['field'] lines, or even loop through all validated data if you want to sync every value.

Testing with your POST example:

Send this JSON request:

{
    "start_time": "2018-11-11T12:00:00Z",
    "end_time": "2018-11-11T12:00:01Z",
    "chamber": "My Test Chamber"
}
  • First request: Creates a new Run instance with the provided data.
  • Second request (with a different end_time): Finds the existing Run and updates its end_time to the new value.

Quick notes:

  • Ensure your Chamber model has a unique field (like name) that matches the value you're sending in the POST request. If you use a different field (like a slug), just update the slug_field in SlugRelatedField.
  • If you're using a view like CreateAPIView, this serializer works out of the box—no extra changes needed in the view.
  • For partial updates (like PATCH requests), you can override the update method similarly, but the above covers the core upsert behavior for POST.

内容的提问来源于stack exchange,提问作者Mormoran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:20:17