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

如何在Django REST API单次请求中更新两个关联模型表字段

单次请求更新关联User与Address表并返回指定格式响应

前提假设

基于Django + Django REST Framework实现,以下是完整的代码解决方案:


1. 模型定义(models.py)

确保User与Address的外键关联正确,通过related_name='addresses'实现用户地址的反向查询:

from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    profile_picture = models.ImageField(upload_to='profile_pictures/', blank=True, null=True)
    date_of_birth = models.DateField(blank=True, null=True)
    gender = models.CharField(max_length=10, choices=[('male', 'Male'), ('female', 'Female'), ('other', 'Other')])
    email = models.EmailField(unique=True)
    phone_number = models.CharField(max_length=20)

class Address(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='addresses')
    street = models.CharField(max_length=255)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    country = models.CharField(max_length=100)
    zip_code = models.CharField(max_length=20)

2. 序列化器实现(serializers.py)

核心通过嵌套序列化器+自定义update方法,同时处理用户基本信息和关联地址的批量更新:

from rest_framework import serializers
from .models import User, Address

class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address
        fields = ['street', 'city', 'state', 'country', 'zip_code']

class UserSerializer(serializers.ModelSerializer):
    addresses = AddressSerializer(many=True)

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'profile_picture', 'date_of_birth', 'username', 'gender', 'email', 'phone_number', 'addresses']
        extra_kwargs = {
            'username': {'required': False}  # 允许username为空值
        }

    def update(self, instance, validated_data):
        # 分离地址数据与用户基本数据
        addresses_data = validated_data.pop('addresses', [])
        
        # 更新用户基本字段
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        # 处理地址更新:采用「删除旧地址+创建新地址」逻辑,若需更新现有地址需传递address_id参数
        instance.addresses.all().delete()
        for addr_data in addresses_data:
            Address.objects.create(user=instance, **addr_data)
        
        return instance

3. 视图编写(views.py)

实现PUT接口,处理单个用户的更新请求:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import User
from .serializers import UserSerializer

class UserProfileUpdateView(APIView):
    def put(self, request, pk):
        try:
            user = User.objects.get(pk=pk)
        except User.DoesNotExist:
            return Response({"error": "用户不存在"}, status=status.HTTP_404_NOT_FOUND)
        
        serializer = UserSerializer(user, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

4. 路由配置(urls.py)

添加更新接口的路由映射:

from django.urls import path
from .views import UserProfileUpdateView

urlpatterns = [
    path('users/<int:pk>/update/', UserProfileUpdateView.as_view(), name='user-profile-update'),
]

5. 测试请求

使用PUT方法调用接口,请求体格式完全匹配你给出的示例JSON:

curl -X PUT http://127.0.0.1:8000/users/1/update/ \
-H "Content-Type: application/json" \
-d '{
    "first_name": "abijith",
    "last_name": "manu",
    "profile_picture": "http://127.0.0.1:8000/media/profile_pictures/my_pic_RxnXQ6n.jpg",
    "date_of_birth": "2024-02-16",
    "username": "",
    "gender": "male",
    "email": "doc@gmail.com",
    "phone_number": "7306986870",
    "addresses": [
        {
            "street": "xvsvf",
            "city": "sss",
            "state": "ssss",
            "country": "ggggggggg",
            "zip_code": "sssssss"
        }
    ]
}'

接口返回的响应格式将与你要求的完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:12:48