【问题标题】:"Incorrect type. Expected pk value, received User."“类型不正确。预期的 pk 值,收到的用户。”
【发布时间】:2021-10-11 23:05:01
【问题描述】:

我有这两个模型:订单和路线。如您所见,该路线与 Order 具有oneToMany 关系:

class Order(models.Model):
    customer = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='customer')
    retailer = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='retailer')
    date_publish = models.DateField(default=datetime.date.today)
    date_available = models.DateField()
    weight = models.DecimalField(decimal_places=2, max_digits=5)
    description = models.CharField(max_length=500, null=True)
    route = models.ForeignKey(Route, related_name='orders', null=True, on_delete=models.CASCADE)

class Route(models.Model):
    day = models.DateField()
    warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE) 
    start_time = models.TimeField()

创建路线后,我想将订单与该路线相关联,因此我完成了以下序列化程序:

class routeSerializer(serializers.ModelSerializer):

    orders = OrderSerializer(many=True)

    class Meta:
        model = Route
        fields = ['day', 'warehouse', 'start_time', 'orders']

    def create(self, validated_data):
        orders_data = validated_data.pop('orders')
        route = Route.objects.create(**validated_data)

        for order_data in orders_data:
            order_serializer = OrderSerializer(data=order_data)
            order_serializer.is_valid(raise_exception=True)
            orders = order_serializer.save()
            orders.route = route
            orders.save()
        
        return route


class OrderSerializer(serializers.ModelSerializer):
    ordertimelocation = orderTimelocationSerializer(many=True)


    class Meta:
        model = Order
        fields = ['id', 'customer', 'retailer', 'date_available', 'weight', 'description', 'ordertimelocation']

    def create(self, validated_data):
        timelocations_data = validated_data.pop('ordertimelocation')
        order = Order.objects.create(**validated_data)
        
        for timelocation_data in timelocations_data:
            order_time_location_serializer = orderTimelocationSerializer(data=timelocation_data)
            order_time_location_serializer.is_valid(raise_exception=True)
            order_time_location = order_time_location_serializer.save()
            order_time_location.order = order
            order_time_location.save()

        return order

    def update(self, instance, validated_data):
        
        timelocations_data = validated_data.pop('ordertimelocation')
        ordertimelocation = instance.ordertimelocation

        for timelocation_data in timelocations_data:
            order_time_location_serializer = orderTimelocationSerializer(data=timelocation_data)
            order_time_location_serializer.is_valid(raise_exception=True)
            order_time_location = order_time_location_serializer.save()
            order_time_location.order = instance
            order_time_location.save()

        return instance

观看次数:

class GetRoutes(generics.ListAPIView):
    queryset = Route.objects.all()
    serializer_class = routeSerializer

class CreateRoute(generics.CreateAPIView):
    queryset = Route.objects.all()
    serializer_class = routeSerializer

class CreateOrder(generics.CreateAPIView):
 
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

class GetOrders(generics.ListAPIView):

    serializer_class = OrderSerializer

    def get_queryset(self):
        us = self.kwargs.get('us')
        return Order.objects.filter(customer_id=us) 
    
class GetOrder(generics.RetrieveAPIView):

    serializer_class = OrderSerializer

    def get_object(self, queryset=None, **kwargs):
        item = self.kwargs.get('order')
        return get_object_or_404(Order, id=item)
    
class UpdateOrder(generics.UpdateAPIView):

    serializer_class = OrderSerializer
    queryset = Order.objects.all()


编辑: 我还像这样自定义了默认用户模型: 用户模型:

class UserManager(BaseUserManager):

    def create_superuser(self, email, user_name, first_name, password, **other_fields):

        other_fields.setdefault('is_staff', True)
        other_fields.setdefault('is_superuser', True)
        other_fields.setdefault('is_active', True)

        if other_fields.get('is_staff') is not True:
            raise ValueError(
                'Superuser must be assigned to is_staff=True.')
        if other_fields.get('is_superuser') is not True:
            raise ValueError(
                'Superuser must be assigned to is_superuser=True.')

        return self.create_user(email, user_name, first_name, password, **other_fields)
    
    def create_user(self, email, user_name, first_name, password, **other_fields):

        if not email:
            raise ValueError(_('You must provide an email address'))

        email = self.normalize_email(email)
        user = self.model(email=email, user_name=user_name, first_name=first_name, **other_fields)
        user.set_password(password)
        user.save()
        return user

class User(AbstractBaseUser, PermissionsMixin):
    GENDER_MALE = 0
    GENDER_FEMALE = 1
    GENDER_OTHER = 2
    GENDER_CHOICES = [(GENDER_MALE, 'Male'), (GENDER_FEMALE, 'Female'), (GENDER_OTHER, 'Other')]

    email = models.EmailField(_('email address'), unique=True)
    user_name = models.CharField(max_length=150, unique=True)
    first_name = models.CharField(max_length=150, blank=True)
    last_name = models.CharField(max_length=150, blank=True)
    start_date = models.DateTimeField(default=timezone.now)
    is_staff = models.BooleanField(default=False)
    is_retailer = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    gender = models.IntegerField(choices=GENDER_CHOICES)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['user_name', 'first_name']

    def __str__(self):
        return self.user_name
    
    def isretailer(self):
        return self.is_retailer

用户序列化器:

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('id', 'email', 'user_name', 'first_name', 'last_name')

观看次数:

class CustomUserCreate(APIView):
    permission_classes = [AllowAny] #when a user create an account he isn't autenticated

    def post(self, request, format='json'):
        serializer = RegisterUserSerializer(data=request.data)
        if serializer.is_valid():
            user = serializer.save()
            if user:
                json = serializer.data
                return Response(json, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class ListUsers(generics.ListAPIView):

    serializer_class = UserSerializer
    queryset = User.objects.all()

class UserDetail(generics.RetrieveAPIView):

    serializer_class = UserSerializer

    def get_object(self, queryset=None, **kwargs):
        item = self.kwargs.get('id')
        return get_object_or_404(User, id=item)

我正在发送这样的请求:

{
    "day" : "2021-12-12",
    "warehouse": "1",
    "start_time": "7:00",
    "orders": [
        {
            "id": 15,
            "customer": 1,
            "retailer": 2,
            "date_available": "2020-12-12",
            "weight": "1.20",
            "description": null,
            "ordertimelocation": [
                {
                    "longitude": "12.1223000000000000",
                    "latitude": "12.1223000000000000",
                    "time_interval": [
                        {
                            "start": "2021-07-21T10:10:00Z",
                            "end": "2021-07-21T10:10:00Z"
                        }
                    ]
                }
            ]
        }
    ]
}

但是服务器返回了一个错误的请求:


{
    "customer": [
        "Incorrect type. Expected pk value, received User."
    ],
    "retailer": [
        "Incorrect type. Expected pk value, received User."
    ]
}

我是 django 的新手,我不知道什么是 'pk' 值以及为什么它期望它而不是用户。

【问题讨论】:

  • 你能分享你的OrderSerializer吗?
  • 分享你的views.py
  • @AyushGupta 共享!
  • 您是否更改了默认的User 模型?
  • @AyushGupta 是的

标签: python django django-rest-framework


【解决方案1】:

PK 是 primary key 在这里等于 id

为了在数据库中保存记录及其关系,django需要相关对象的PK

但是当你将这个pk传递给序列化器时,在序列化器的validate()函数中,django如果传递的pk在db中存在并且有效,则返回它的模型对象

例如,您将客户 pk 作为 1 传递,但在验证后,有一个 ID 为 1 的 Customer 对象。您将此对象传递给 order = Order.objects.create(**validated_data) 但正如我之前提到的,您应该只传递 PK

所以解决方案之一可以是:

validated_data['customer'] = validated_data['customer'].id
validated_data['retailer'] = validated_data['retailer'].id
order = Order.objects.create(**validated_data)

另一个解决方案是覆盖 validate() 函数并控制返回的内容

【讨论】:

    猜你喜欢
    • 2015-08-26
    • 2021-09-06
    • 2020-09-09
    • 2017-06-14
    • 2021-07-03
    • 2018-10-05
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    相关资源
    最近更新 更多