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

Django后端报错:main_order表customer_id违反非空约束

问题描述

提交订单时触发数据库非空约束错误:

null value in column "customer_id" of relation "main_order" violates not-null constraint DETAIL: Failing row contains (58, 2023-07-20 09:32:15.565247+00, null)

虽然在OrdersList视图的post方法中打印request.POST能看到<QueryDict: {'customer': ['7']}>,但保存订单时customer_id仍为null。

代码详情

views.py

class OrdersList(generics.ListCreateAPIView):
    queryset = models.Order.objects.all()
    serializer_class = serializers.OrderSerializer

    def post(self, request, *args, **kwargs):
        print(request.POST)
        return super().post(request, *args, **kwargs)

class OrderDetails(generics.ListAPIView):
    queryset = models.OrderItems.objects.all()
    serializer_class = serializers.OrderDetailsSerializer

    def get_queryset(self):
        order_id = self.kwargs['pk']
        order = models.Order.objects.get(id=order_id)
        order_items=models.OrderItems.objects.filter(order=order)
        return order_items

models.py

class Order(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='customer_orders')
    order_time = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '%s' % (self.order_time)

class OrderItems(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='order_items')
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

    def __str__(self):
        return self.product.title

serializers.py

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Order
        fields = ['id', 'customer']

    def __init__(self, *args, **kwargs):
        super(OrderSerializer, self).__init__(*args, **kwargs)
        self.Meta.depth = 1

请求负载

-----------------------------7872495127917832492110041678
Content-Disposition: form-data; name="customer"

7
-----------------------------7872495127917832492110041678--

完整报错栈

Internal Server Error: /api/orders/
Traceback (most recent call last):
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/opt/homebrew/lib/python3.10/site-packages/psycopg/cursor.py", line 723, in execute
    raise ex.with_traceback(None)
psycopg.errors.NotNullViolation: null value in column "customer_id" of relation "main_order" violates not-null constraint
DETAIL:  Failing row contains (64, 2023-07-20 10:37:10.07752+00, null).

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/homebrew/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/opt/homebrew/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/opt/homebrew/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
  File "/opt/homebrew/lib/python3.10/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/burteanupamnarayan/DistributedRepo2023/project/main/views.py", line 138, in post
    return super().post(request, *args, **kwargs)
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/generics.py", line 242, in post
    return self.create(request, *args, **kwargs)
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/mixins.py", line 19, in create
    self.perform_create(serializer)
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/mixins.py", line 24, in perform_create
    serializer.save()
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/serializers.py", line 212, in save
    self.instance = self.create(validated_data)
  File "/opt/homebrew/lib/python3.10/site-packages/rest_framework/serializers.py", line 962, in create
    instance = ModelClass._default_manager.create(**validated_data)
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/query.py", line 658, in create
    obj.save(force_insert=True, using=self.db)
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/base.py", line 814, in save
    self.save_base(
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/base.py", line 877, in save_base
    updated = self._save_table(
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/base.py", line 1020, in _save_table
    results = self._do_insert(
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/base.py", line 1061, in _do_insert
    return manager._insert(
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/query.py", line 1805, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1820, in execute_sql
    cursor.execute(sql, params)
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/backends/utils.py", line 102, in execute
    return super().execute(sql, params)
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/backends/utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/opt/homebrew/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/opt/homebrew/lib/python3.10/site-packages/psycopg/cursor.py", line 723, in execute
    raise ex.with_traceback(None)

问题原因

核心问题出在OrderSerializer中的depth=1配置:
当设置depth=1时,DRF的ModelSerializer会将外键字段序列化为嵌套对象结构,而非单纯的主键ID。此时序列化器期望接收的customer是包含Customer模型字段的字典,而不是前端传入的主键值7。因此前端的参数无法被序列化器解析,导致validated_data中缺失customer字段,最终保存Order时customer_id为null,触发数据库非空约束错误。


解决方法

提供两种可行方案,根据业务需求选择:

方案1:移除depth=1配置

如果不需要返回嵌套的Customer对象,直接删除序列化器中的depth设置:

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Order
        fields = ['id', 'customer']
    # 删除原__init__方法中的depth设置代码

方案2:显式定义字段类型兼容输入输出

如果需要保持depth=1用于返回嵌套的Customer对象,同时允许接收主键ID作为输入,显式指定customer字段类型:

class OrderSerializer(serializers.ModelSerializer):
    # 输入时接收主键ID,输出时自动嵌套序列化
    customer = serializers.PrimaryKeyRelatedField(queryset=models.Customer.objects.all())
    
    class Meta:
        model = models.Order
        fields = ['id', 'customer']
        depth = 1

调试建议

可以在视图的post方法中添加打印验证后数据的代码,确认customer是否被正确解析:

def post(self, request, *args, **kwargs):
    print(request.POST)
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    print(serializer.validated_data)  # 查看验证后的数据是否包含customer
    return super().post(request, *args, **kwargs)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 16:17:10