将PrimaryKeyRelatedField替换为另一个字段

时间:2016-12-02 21:36:47

标签: python django django-rest-framework

我的模型包含User模型和Present模型。 User可以有多个Present,但Present有唯一的User

我的models.py是:

from django.db import models
from django.contrib.auth.models import User

class Present(models.Model):
    name = models.CharField(max_length=15)
    price = models.FloatField()
    link = models.CharField(max_length=15)
    isAlreadyBought = models.BooleanField()
    user = models.ForeignKey(User, related_name='presents', on_delete=models.CASCADE)

我的serializers.py是:

from django.contrib.auth.models import User, Group
from rest_framework import serializers
from blog.models import Present, Location
from django.contrib.auth.models import User


class UserSerializer(serializers.ModelSerializer):

    presents = serializers.PrimaryKeyRelatedField(many=True, queryset=Present.objects.all(), required=False)

    class Meta:
        model = User
        fields = ('username', 'password', 'email', 'presents')

    def create(self, validated_data):
        user = super().create(validated_data)
        if 'password' in validated_data:
                user.set_password(validated_data['password'])
                user.save()
        return user



class PresentSerializer(serializers.ModelSerializer):

    user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), read_only=False, many=False)

    class Meta:
        model = Present
        fields = ('name', 'link', 'price', 'isAlreadyBought', 'user')

    def create(self, validated_data):
        return Present.objects.create(**validated_data)

目前,如果我想获得与给定用户关联的所有礼物,我使用主键(在views.py中):

class PresentsOfUser(viewsets.ModelViewSet):
    queryset = Present.objects.all().filter(user=33)
    serializer_class = PresentSerializer

但是,我宁愿使用username的{​​{1}}字段而不是主键。

我尝试使用User,但我不确定这是实现目标的正确方法:

SlugRelatedField

通过此修改,我现在使用以下class PresentSerializer(serializers.ModelSerializer): user = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='username', read_only=False, many=False) class Meta: model = Present fields = ('name', 'link', 'price', 'isAlreadyBought', 'user') def create(self, validated_data): return Present.objects.create(**validated_data) 来获取View'Marcel'的用户id

33

但在这种情况下,我得到:

class PresentsOfUser(viewsets.ModelViewSet):
    queryset = Present.objects.all().filter(user='Marcel')
    serializer_class = PresentSerializer

但如果我将ValueError: invalid literal for int() with base 10: 'Marcel' 替换为user='Marcel'(如前所述),我会得到:

user=33

用户字段现在是[{"name":"Nintendo","link":"fake_link","price":50.8,"isAlreadyBought":true,"user":"Marcel"},{"name":"Gamecube","link":"fake_link","price":50.8,"isAlreadyBought":true,"user":"Marcel"}] 而不是用户的username

但是,我不明白为什么使用id进行过滤会失败...

1 个答案:

答案 0 :(得分:1)

我最终通过覆盖get_queryset方法,同时将PrimaryKeyRelatedField保留在我的序列化程序中(user__username='Marcel'为mishbah建议):

class PresentsOfUser(viewsets.ModelViewSet):

    serializer_class = PresentSerializer

    def get_queryset(self):
        """
        Optionally restricts the returned purchases to a given user,
        by filtering against a `username` query parameter in the URL.
        """
        queryset = Present.objects.all()
        username = self.kwargs['user']
        if username is not None:
            queryset = queryset.filter(user__username=username)

        if len(queryset) == 0:
            raise Http404

        return queryset

PrimaryKeyRelatedField替换为SlugRelatedField时,它也有效:

user = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='username', read_only=False, many=False)

并在to_field='username'模型的ForeignKey中添加Present

user = models.ForeignKey(User, related_name='presents', to_field='username', on_delete=models.CASCADE)