2017-11-15 15 views
0

本当にこれに苦労していて、本当にストレートなはずです。基本的には、私はユーザーに関連付けられた製品を試しているだけで、FE上でレンダリングされる製品はそれぞれshort_nameです。Django RESTフレームワークの外部キー関係のテーブルから関連するデータを読み込む

私はuser_idprod_idのテーブルを持っています。表は次のようになります。

user_id | prod_id 
----------------- 
2  | 42 
2  | 2 
2  | 21 
13  | 7 
13  | 17 
13  | 2 

user_idUserテーブルへmodels.ForeignKeyあるとprod_idmodels.ForeignKeyProductsにテーブルです。いっそのこと、こちらのモデルです:

# ./home/models.py 
from django.contrib.auth import get_user_model 
from django.db import models 

User = get_user_model() 

class Product(models.Model): 
    id = models.AutoField(primary_key=True) 
    code = models.CharField(unique=True, max_length=16) 
    name = models.CharField(max_length=255, blank=True, null=True) 
    short_name = models.CharField(max_length=128) 
    updated = models.DateTimeField(blank=True, null=True) 
    created = models.DateTimeField(blank=True, null=True) 

    def __str__(self): 
     return self.short_name 

    class Meta: 
     db_table = 'Product' 

class UserToProduct(models.Model): 
    user = models.ForeignKey(User, related_name='user_name', db_column='user_id', null=True) 
    prod = models.ForeignKey(Product, related_name='prod_name', db_column='prod_id', null=True) 

    class Meta: 
     db_table = 'User_to_Product' 
     unique_together = ('user', 'prod') 

起こってどうあるべきかは、リアクトのフロントエンドであるジャンゴ/ DRFバックエンドにログインしているユーザーに基づいてuser_idを送信します。これはうまく起こっています。ここでは、関連するビューは次のとおりです。

# ./home/views.py 
from rest_framework.permissions import IsAuthenticated 
from rest_framework.response import Response 
from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST 
from rest_framework.views import APIView 

from .serializers import GetProductSerializer 
from .models import Home 

class GetHomeAPIView(APIView): 
    permission_classes = [IsAuthenticated] 

    def post(self, request, *args, **kwargs): 
     serializer = GetProductSerializer(data=request.data) 
     if serializer.is_valid(raise_exception=True): 
      return Response(serializer.data, status=HTTP_200_OK) 
     return Response(serializer.errors, status=HTTP_400_BAD_REQUEST) 

そこから、それはちょうどそれらに関連する製品のリストを引っ張って、その後Productモデルからshort_nameの読み込み、または実際に私が出て解析できるだけのオブジェクトする必要がありますshort_nameNameError: name 'data' is not defined

# ./home/serializers.py 
from rest_framework.serializers import (
    IntegerField, 
    ModelSerializer, 
    SerializerMethodField, 
    StringRelatedField, 
) 

from .models import * 

class GetProductSerializer(ModelSerializer): 
    prod_name = StringRelatedField(many=True, required=False) 
    product = SerializerMethodField('get_products') 

    class Meta: 
     model = UserToProduct 
     fields = ('user', 'prod', 'prod_name') 

    def get_products(self, obj): 
     products = UserToProduct.objects.filter(user=data['user']) 
     return products 

この特定の変化は、その結果:ここ

は、シリアライザです。

変更get_products()は持っている:私は認めざるを得ない気よりも、この上KeyError: 'prod_name'

とにかく、私が費やしているより多くの時間:これは、その結果

# for testing reasons 
products = UserToProduct.objects.filter(user=2) 

。これは本当に基本的なものです。私は何十種類ものバリエーションを試しました。私はそれに取り組んで、私が試したこととエラーを投稿します。あまりにもこのに関する無数の他のSO質問/回答を参考にしてちょうど働いていない

http://www.django-rest-framework.org/api-guide/relations/

http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/

また、これは私が何十回を読んでいることを参照していますドキュメントがあります。

EDIT:おそらく数十を試してみて、最終的にサーバからのシリアル化された応答を得ることができました。しかし、それはshort_nameを持ち込んでいません。私が行った変更のみ:中

prod = UserToProduct.objects.filter(user=obj['user']) 

結果:TypeError: Object of type 'UserToProduct' is not JSON serializableまた

# ./home/models.py 
class Product(models.Model) 
    ... 
    users = models.ManyToManyField(User, through='UserToProduct') 

# ./home/serializers.py 
class GetProductSerializer(ModelSerializer): 
    user = IntegerField() # have to do this otherwise it returns the username and not the id 
    prod = SerializerMethodField() 

    class Meta: 
     model = UserToProduct 
     fields = [ 
      'user', 
      'prod', 

     ] 

    def get_prod(self, obj): 
     prod = UserToProduct.objects.filter(user=obj['user']).values('prod') 
     print(prod) 
     return prod 

、重要に注意することは、ちょうどget_prod()などを残しています。ただし、short_nameprint(prod)に記載しています。

+0

UserToProductは多対多リレーションシップのスルーテーブルです。そのように宣言する必要があります。 –

答えて

0

最後に、私はそれが機能していると思います。それは信じられないほど遅く、本当に正しいと思わない情報を返すのに約5秒かかります。これはデータ量が長すぎます。

はとにかく、これはそれが私のために働いて得たものである:私がしようとしていたよりも、よりシンプル

# ./home/views.py 
... 
def post(self, request, *args, **kwargs): 
    user = request.data['user'] 
    serializer = GetProductSerializer(UserToProduct.objects.filter(user=user).prefetch_related('prod'), many=True) 
    return Response(serializer.data) 

# ./home/serializers.py 
class GetProductSerializer(ModelSerializer): 
    prod = CharField() # otherwise it was using prod_id number 

    class Meta: 
     model = UserToProduct 
     fields = [ 
      'prod' 
     ] 

ウェイ...ただスピードの問題を整理するために外に出ました。

EDIT:

UserToProduct.objects.filter(user=user).prefetch_related('prod') 

そして、それはに4.75秒から下った次に私のクエリを修正

Optimizing database queries in Django REST framework

:このの助けのおかげでSOポストスピード問題を修正しました1.5秒。 Yee-haw。

関連する問題