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

Django DRF提交Residence数据报错:got an unexpected keyword argument 'hotel_id'

Django外键关联POST提交报错解决方案

报错根因

出现这个报错有两个核心问题:

  • 外键字段命名不符合Django ORM规范:你给外键字段命名为hotel_id,Django处理外键时会自动给存储主键的数据库列追加_id后缀,最终对应数据库字段变为hotel_id_id,直接传递hotel_id参数创建Residence实例时,ORM无法匹配到正确的字段赋值逻辑,尤其你嵌套了Hotel序列化器后,hotel_id对应的是酒店字典数据,不是合法的Hotel实例。
  • 嵌套序列化的创建逻辑未处理关联数据:你直接将包含嵌套酒店字典的validated_data传给Residence.objects.create(),没有提前将酒店数据转为对应的Hotel实例。

修复步骤

第一步:调整模型外键命名(必改,避免后续字段映射混乱)

修改Residence模型的外键字段命名为常规的hotel,同时调整related_name为反向查询更合理的命名,另外补上所有CharField必填的max_length参数:

class Hotel(models.Model):
    name = models.CharField(max_length=100)
    country = models.CharField(max_length=100)
    city = models.CharField(max_length=100)
    street = models.CharField(max_length=200) 

class Residence(models.Model):
    # 把原hotel_id改为hotel,符合ORM命名规范
    hotel = models.ForeignKey(Hotel, on_delete=models.DO_NOTHING, related_name='residences')
    house_number = models.CharField(max_length=50)

第二步:根据业务场景调整序列化器

场景1:提交Residence时同时创建关联的新Hotel

修改ResidenceSerializer的create方法,先提取酒店数据创建Hotel实例,再用该实例创建Residence:

class HotelSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Hotel
        fields = ['name', 'country', 'city', 'street']

class ResidenceSerializer(serializers.HyperlinkedModelSerializer):
    hotel = HotelSerializer()

    class Meta:
        model = Residence
        fields = ['house_number', 'hotel'] 
 
    def create(self, validated_data):
        # 先取出嵌套的酒店数据
        hotel_data = validated_data.pop('hotel')
        # 创建酒店实例
        hotel = Hotel.objects.create(**hotel_data)
        # 把酒店实例传入创建Residence
        return Residence.objects.create(hotel=hotel, **validated_data)

场景2:提交Residence时仅关联已有的Hotel,无需新增酒店

不需要可写的嵌套HotelSerializer,直接用主键关联即可,如果需要返回接口时带酒店详情,可以把HotelSerializer设为只读,额外加可写的酒店id字段:

class ResidenceSerializer(serializers.HyperlinkedModelSerializer):
    # 只读,返回时展示酒店详情
    hotel = HotelSerializer(read_only=True)
    # 可写,提交时传已有的酒店id
    hotel_id = serializers.PrimaryKeyRelatedField(
        queryset=Hotel.objects.all(),
        source='hotel',
        write_only=True
    )

    class Meta:
        model = Residence
        fields = ['house_number', 'hotel', 'hotel_id'] 

这种场景下POST提交时只需要传house_number和hotel_id两个字段即可,无需传整个酒店的详细信息。

第三步:迁移模型生效修改

修改完模型后执行以下命令更新数据库结构:

python manage.py makemigrations
python manage.py migrate

调整完之后再次调用POST接口即可正常提交数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:54:04