2016-12-02 5 views
0

Ich habe Modelle, die in einem User Modell und einem Present eins bestehen. Ein User können mehrere Present haben aber eine Present hat eine einzigartige User:Ersetzen PrimaryKeyRelatedField durch ein anderes Feld

Mein models.py ist:

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) 

Meine serializers.py sind:

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) 

Derzeit, wenn ich das alles bekommen präsentiert assoziieren mit einem bestimmten Benutzer, verwende ich den Primärschlüssel (in views.py):

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

Allerdings würde ich lieber das username Feld des User anstelle des Primärschlüssels verwenden. ein SlugRelatedField aber ich bin nicht sicher, dass dies der richtige Weg, mit meinem Ziel zu erreichen

Ich habe versucht:

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) 

Und mit dieser Modifikation ich nun folgenden View verwenden, um die Benutzer 'Marcel' deren id zu erhalten 33 ist:

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

Aber in diesem Fall, die ich erhalten:

ValueError: invalid literal for int() with base 10: 'Marcel' 

Aber wenn ich user='Marcel' von user=33 (wie bisher) ersetzen, die ich erhalte:

[{"name":"Nintendo","link":"fake_link","price":50.8,"isAlreadyBought":true,"user":"Marcel"},{"name":"Gamecube","link":"fake_link","price":50.8,"isAlreadyBought":true,"user":"Marcel"}] 

, wo der Benutzer Feld jetzt ist die username und nicht die der Benutzer id.

Allerdings verstehe ich nicht, warum mit Filtern user='Marcel' versagt ...

+0

Haben Sie "user__username" in den Feldern des aktuellen Serializers ausprobiert? – Brobin

+0

Könnten Sie Einzelheiten? – floflo29

Antwort

1

Ich denke, Ihr Problem w/diese Linie ist:

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

Mit der Annahme Marcel ist Benutzername mit pk = >33

Sie können nicht mithilfe einer Zeichenfolge filtern, stattdessen etwa so:

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

Hoffe, dass hilft.

+0

Verwenden von 'PrimaryKeyRelatedField' oder' SlugRelatedField' in meinem vorhandenen Serializer? – floflo29

+0

Wenn Sie 'Benutzername' anstelle von 'pk' Wert verwenden möchten, würden Sie 'SlugRelatedField' verwenden. – mishbah

0

landete ich durch Überschreiben der get_queryset Methode, während die PrimaryKeyRelatedField in meinem Serializer zu halten (mit user__username='Marcel' als mishbah vorgeschlagen):

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 

Es funktioniert auch, wenn PrimaryKeyRelatedField durch SlugRelatedField ersetzt:

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

und Hinzufügen von to_field='username' in der ForeignKey von meinem Present Modell:

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