簡體   English   中英

用另一個字段替換PrimaryKeyRelatedField

[英]Replace PrimaryKeyRelatedField with another field

我有一些模型,其中包括一個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

但是,我寧願使用Userusername字段代替主鍵。

我曾嘗試使用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獲取id33的用戶'Marcel'

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"}]

其中user字段現在是username而不是用戶的id

但是,我不明白為什么用user='Marcel'過濾失敗...

我認為您的問題在於此行:

queryset = Present.objects.all().filter(user='Marcel')

假設Marcelpk => 33用戶名

您不能使用字符串進行過濾,而是使用類似以下的內容:

queryset = Present.objects.all().filter(user__username='Marcel')

希望能有所幫助。

最后,我覆蓋了get_queryset方法,同時將PrimaryKeyRelatedField保留在序列化程序中(如mishbah建議使用user__username='Marcel' ):

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

當用SlugRelatedField替換PrimaryKeyRelatedField時,它也可以工作:

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

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM