2016-12-02 63 views
0

我有一個模型,它包含User模型和一個Present。一個User可以有多個PresentPresent具有獨特的User用另一個字段替換PrimaryKeyRelatedField

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獲得'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

不過,我不明白爲什麼有user='Marcel'失敗過濾...

+0

您是否在本串行器的字段中嘗試過''user__username''? – Brobin

+0

你能否詳細說明? – floflo29

回答

1

我覺得你的問題是W /這一行:

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

的假設Marcel是用戶名與pk = >33

你不能使用字符串進行過濾,而應該像這樣:

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

希望有所幫助。

+0

在我的序列化程序中使用'PrimaryKeyRelatedField'或'SlugRelatedField'? – floflo29

+0

如果你想'username'而不是'pk'的值..你會使用'SlugRelatedField'。 – mishbah

0

我最終通過重寫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 

通過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)