Django实现非主键的客户订单号自动递增方案
解决Django中客户订单order_number按客户自动递增的问题
需求
实现每个客户提交的订单的order_number字段自动递增,且不修改Order模型的主键(primary_key)。
现有代码
Models.py
class Customer(models.Model): customer_name = models.CharField(max_length=100) customerID = models.CharField(max_length=100) class Order(models.Model): customer = models.ForeignKey(Customer, related_name='order', on_delete=models.CASCADE) order_name = models.CharField(max_length=100) order_number = models.IntegerField(default=0)
Serializers.py
from rest_framework import serializers from .models import * class OrderSerializer(serializers.ModelSerializer): class Meta: model = Order fields = '__all__' class CustomerSerializer(serializers.ModelSerializer): orders = OrderSerializer(many=True, read_only=True, required=False) class Meta: model = Customer fields = '__all__'
views.py
from rest_framework import generics, status from rest_framework.views import APIView from rest_framework.response import Response from django.shortcuts import get_object_or_404 from .models import * from .serializers import * class CustomerListView(generics.ListCreateAPIView): queryset = Customer.objects.all() serializer_class = CustomerSerializer class CustomerDetailView(generics.RetrieveDestroyAPIView): queryset = Customer.objects.all() serializer_class = CustomerSerializer class OrderListView(generics.ListCreateAPIView): def get_queryset(self): queryset = Order.objects.filter(customer_id=self.kwargs["pk"]) return queryset serializer_class = OrderSerializer class OrderDetailView(generics.RetrieveDestroyAPIView): serializer_class = OrderSerializer def get_queryset(self): queryset = Order.objects.filter(id=self.kwargs["pk"]) return queryset
urls.py
from django.urls import path from .views import * urlpatterns = [ path('', CustomerListView.as_view(), name=''), path('<int:pk>/', CustomerDetailView.as_view(), name=''), path('<int:pk>/orders/', OrderListView.as_view(), name=''), path('<int:customer_pk>/orders/<int:pk>/', OrderDetailView.as_view(), name=''), ]
期望返回示例
[ { "id": 1, "order": [ { "id": 1, "order_name": "fruit", "order_number": 1, "customer": 1 }, { "id": 2, "order_name": "chair", "order_number": 2, "customer": 1 }, { "id": 3, "order_name": "pc", "order_number": 3, "customer": 1 } ], "customer_name": "john doe", "customerID": "81498" }, { "id": 2, "order": [ { "id": 4, "order_name": "phone", "order_number": 1, "customer": 2 }, { "id": 5, "order_name": "car", "order_number": 2, "customer": 2 } ], "customer_name": "jane doe", "customerID": "81499" } ]
解决方案
要实现按客户单独递增order_number,只需在Order模型中重写save方法,针对当前客户的已有订单计算编号:
修改后的Models.py代码
from django.db import models class Customer(models.Model): customer_name = models.CharField(max_length=100) customerID = models.CharField(max_length=100) class Order(models.Model): customer = models.ForeignKey(Customer, related_name='order', on_delete=models.CASCADE) order_name = models.CharField(max_length=100) order_number = models.IntegerField(default=0) def save(self, *args, **kwargs): # 仅在新建订单时自动生成编号 if not self.pk: # 获取当前客户已有的最大order_number last_num = Order.objects.filter(customer=self.customer).aggregate(largest=models.Max('order_number'))['largest'] # 无订单则从1开始,否则递增 self.order_number = last_num + 1 if last_num is not None else 1 super().save(*args, **kwargs)
关键修改说明
原方案中若使用全局获取最大编号的逻辑(last_id = self.objects.all().aggregate(largest=models.Max('display_id'))['largest']),会导致所有客户的订单编号连续递增,无法实现按客户独立计数。我们需要将其修改为针对当前客户过滤订单,只计算该客户的最大order_number:
last_num = Order.objects.filter(customer=self.customer).aggregate(largest=models.Max('order_number'))['largest']
修改后,每次为客户创建新订单时,系统会自动生成该客户专属的递增编号,完全符合需求。
内容的提问来源于stack exchange,提问作者mRezaAnanta
相关产品推荐
相关产品推荐

