2016-12-02 65 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)