【问题标题】:Django Auto Increment Field Non PkDjango 自动增量字段非 Pk
【发布时间】:2022-11-01 13:45:32
【问题描述】:

如何制作模型,以便客户提交的每个订单都会自动递增(即 order_number)而不会弄乱订单 obj primary_key?

模型.py

class Costumer(models.Model):
    costumer_name = models.CharField(max_length=100)
    costumerID = models.CharField(max_length=100)

class Order(models.Model):
    costumer = models.ForeignKey(Costumer, related_name='order', on_delete=models.CASCADE)
    order_name = models.CharField(max_length=100)
    order_number = models.IntegerField(default=0)

序列化程序.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__'

视图.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

网址.py

from django.urls import path

from .views import *

urlpatterns = [
    path('', CustomerListView.as_view(), name='players_list'),    
    path('<int:pk>/', CustomerDetailView.as_view(), name='players_detail'),    
    path('<int:pk>/orders/', OrderListView.as_view(), name='characters_list'),    
    path('<int:customer_pk>/orders/<int:pk>/', OrderDetailView.as_view(), name='characters_detail'),    
]

JSON 示例

[
    {
        "id": 1,
        "order": [
            {
                "id": 1,
                "order_name": "fruit",
                "order_number": 1,
                "costumer": 1
            },
            {
                "id": 2,
                "order_name": "chair",
                "order_number": 2,
                "costumer": 1
            },
            {
                "id": 3,
                "order_name": "pc",
                "order_number": 3,
                "costumer": 1
            }
        ],
        "costumer_name": "john doe",
        "costumerID": "81498"
    },
    {
        "id": 2,
        "order": [
            {
                "id": 4,
                "order_name": "phone",
                "order_number": 1,
                "costumer": 2
            },
            {
                "id": 5,
                "order_name": "car",
                "order_number": 2,
                "costumer": 2
            }
        ],
        "costumer_name": "jane doe",
        "costumerID": "81499"
    }
]

如果我需要提交更多文件,例如 seriallizers.py 等,请告诉我。先感谢您。

编辑

添加更多文件。

【问题讨论】:

    标签: python django django-models django-rest-framework django-views


    【解决方案1】:

    您可以使用自动字段。 django 文档在这里谈到了这一点:https://docs.djangoproject.com/en/3.2/ref/models/fields/#autofield

    【讨论】:

    • 感谢您的评论,但是当我尝试使用自动字段时,它只会给我这个错误ValueError: Model temp.Order can't have more than one auto-generated field.
    【解决方案2】:

    我认为可行的是使用IntegerField(几乎是AutoField 在后台使用的),并在模型的第一次保存时增加它(在它被放入数据库之前)。

    例子:

    from django.db import models
    
    class MyModel(models.Model):
    
        # This is what you would increment on save
        # Default this to one as a starting point
        display_id = models.IntegerField(default=1)
    
        # Rest of your model data
    
        def save(self, *args, **kwargs):
            # This means that the model isn't saved to the database yet
            if self._state.adding:
                # Get the maximum display_id value from the database
                last_id = self.objects.all().aggregate(largest=models.Max('display_id'))['largest']
    
                # aggregate can return None! Check it first.
                # If it isn't none, just use the last ID specified (which should be the greatest) and add one to it
                if last_id is not None:
                    self.display_id = last_id + 1
    
            super(MyModel, self).save(*args, **kwargs)
    

    【讨论】:

    • 嗨 ilyasbbu,谢谢你的评论。我试过你的解决方案,但它给了我这个错误AttributeError: Manager isn't accessible via Order instances你知道为什么会发生吗?
    • 我不知道您是如何实现的,也许如果我看到代码我可以说出原因。
    • 我应该像 serializers.py 等一样显示它的所有代码吗?
    【解决方案3】:

    您可以在创建订单时覆盖保存功能,并根据其他客户订单的最大值设置该点的订单号

    class Order(models.Model):
        costumer = models.ForeignKey(Costumer, 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:
                # get all your customers orders and get the last order number
                last_order = self.customer.order.all().order_by('order_number').last()
                self.order_number = last_order.order_number + 1
            
            super(Order, self).save(*args, **kwargs)
    
    

    【讨论】:

    • 谢谢你的评论,但它给了我这个错误~~~文件“/home/mrezaananta/Documents/GitHub/temp-backend/temp/models.py”,第29行,保存self.order_number = last_order.order_number + 1 AttributeError: 'NoneType' object has no attribute 'order_number' ~~~你知道为什么会这样吗?
    猜你喜欢
    • 2015-12-08
    • 1970-01-01
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 2021-05-29
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多