2017-10-02 8 views
1

Disons que j'ai deux modèles.Django Rest DRF: accès à une référence de clé étrangère à partir de la relation inverse

Modèle

class Item(models.Model): 
    name = models.CharField(max_length=32) 
    # other fields 

class ItemRelation(models.Model): 
    item = models.ForeignKey(Item, related_name='relations_item') 
    user = models.ForeignKey(User, related_name='relations_user') 
    has_viewed = models.BooleanField(default=False) 
    has_loved = models.BooleanFields(default=False) 

Maintenant, ce que je veux faire est d'obtenir le profil d'un utilisateur qui contiendrait les éléments associés à cet utilisateur ayant has_loved = True et has_viewed = True.

Dans mon fichier views.py, j'avais quelque chose comme ça.

class UserProfile(APIView): 
    def get(self, request, format=None): 
     id = self.request.query_params.get('id') 
     user = User.objects.filter(id=id).prefetch_related(Prefetch(
      'relations_user', queryset=ItemRelation.objects.select_related('item').filter(has_viewed=True), 
      to_attr='item_viewed' 
    )) 

J'étais certain que je me suis trompé et j'ai aussi eu une erreur de sérialiseur, depuis que je suis en train de sérialisation un objet ItemRelation à l'aide d'un sérialiseur qui a utilisé l'élément comme son modèle.

EDIT

serializers.py

class ItemSerializer(seralizer.ModelSerializer): 
    class Meta: 
     model = Item 
     fields = ['name'] 

class UserSerializer(serializers.ModelSerializer): 
    relations_user = ItemSerializer(read_only=True, many=True) 
    class Meta: 
     model = User 
     fields = ['username', 'relations_user'] 
+0

où êtes-vous sérialiseurs? montre le '' 'serializers.py'''. Et vous ne déclarez pas '' '' serializer_class''' dans votre vue. – Bestasttung

+0

bien n'utilisant pas rest_framework.generics ici donc pas serializer_class, et aussi je suis certain que mon problème réside dans la façon dont j'interroge les éléments en utilisant Prefetch. – flaire

+1

vous parlez d'une erreur sérialiseur, pourquoi en parlez-vous s'il n'y a pas de problème? – Bestasttung

Répondre

0

Tout d'abord: Il semble que vous essayez de modéliser une sorte de plusieurs à plusieurs dans vos données et il serait être mieux en utilisant le Django approprié ManyToManyField.

Cela étant dit, une solution possible à votre problème peut ressembler à ceci, la mise en œuvre via un SerializerMethodField:

views.py

class UserProfile(APIView): 
    def get(self, request, format=None): 
     pk = self.request.query_params.get('id') 

     # consider using get_object_or_404 here or implement some 
     # other sort of error handling for a failed lookup 
     user = User.objects.get(pk=pk) 

serializers.py

from .models import Item 


class ItemSerializer(seralizer.ModelSerializer): 
    class Meta: 
     model = Item 
     fields = ['name'] 

class UserSerializer(serializers.ModelSerializer): 
    items = serializers.SerializerMethodField() 

    class Meta: 
     model = User 
     fields = ['username', 'items'] 

    def get_items(self, obj): 
     # obj is the User instance you call the serializer with 
     items = Item.objects.filter(
        relations_item__user=obj, 
        relations_item__has_viewed=True, 
        relations_item__has_loved=True, 
       ) 

     # serialize the items with your ItemSerializer defined above 
     serializer = ItemSerializer(items, many=True) 

     return serializer.data 

Fondamentalement, vous utilisez un SerializerMethodField qui donne le coup de pied un filtrage de requête supplémentaire pour les éléments qui sont liés à l'utilisateur et ont les propriétés has_viewed==True et has_loved==True.

Notez que ce n'est pas optimale car:

  • Vous exécutez une requête supplémentaire dans votre sérialiseur.
  • Vous modélisez manuellement une relation plusieurs-à-plusieurs sans utiliser le champ Django approprié (voir ci-dessus).
  • Dans ce cas, nous utilisons manuellement un SerializerMethodField au lieu de laisser DRF s'occuper de l'affichage des relations.
+0

c'est ce que je fais actuellement, et bien cela fait beaucoup de hits à la base de données, Merci pour le retour si – flaire