2015-11-14 4 views
9

多くのデータがある場合は、ネストされたリレーションシップまたはPrimaryKeyRelatedフィールドを使用する方が良いですか?django-REST:ネストされたリレーションシップとPrimaryKeyRelatedField

私は深い関係を持つモデルを持っています。
わかりやすくするために、私は列を追加しませんでした。

モデル:

Model

ユースケース:

  1. ユーザー2つのワークアウトおよび3 WorkoutExercisesと1 Workoutplanを作成します。
  2. ユーザーは、WorkoutExercise/Exerciseごとに6つのセットを作成します。
  3. ユーザーはFinishedSetで新しいFinishedWorkoutExerciseが

質問に作成された>>新しいFinishedWorkoutが作成され

  • ユーザーが最初の演習を行い、使用される重みに入るトレーニングを開始します:私は進行を追跡する

    を各ワークアウトプラン>エクササイズ>エクササイズについて。 時間があれば、ユーザーは数十回のワークアウトを完了している可能性があります。

    ここでネストされたリレーションシップを使用すると、私は必要のない多くのデータを読み込むことがあります。 しかし、私はPrimaryKeyRelatedFieldsを使用する場合、私は別に必要なすべてのデータをロードする必要があります。これは私のフロントエンドでもっと努力することを意味します。

    このような状況では、どの方法が適していますか?

    編集:私はPrimaryKeyRelatedFieldsを使用している場合
    どのように私は区別しない場合、例えばWorkoutplanのワークアウトは、主キーを持つ配列か、ロードされたオブジェクトを持つ配列ですか?あなたがPrimaryKeyRelatedFieldを使用している場合

  • +0

    ここでコードはありますか? – dnozay

    +0

    NestedRelを変更するので、コードは必要ではないと思いました。 to PrimaryKeyRelatedEntitiesはちょうどdjangoモデルの簡単なコードのほんの数行です。フロントエンドでの検索は、両方でほぼ同じです。 – Altoyyr

    答えて

    1

    、あなたの場合は

    フロントエンド

    に必要なデータを要求する大きな過負荷があるでしょう、私はあなたが( Meta.fields属性を使用して)したいフィールドを持つ特定のシリアライザを作成します。したがって、不要なデータはロードされず、フロントエンドはバックエンドからさらにデータを要求する必要はありません。

    詳細が必要な場合は、サンプルコードを書くことができます。

    +0

    私は同意します。 WorkoutCreateSerializerの代わりにWorkoutCreateSerializerを使用するかどうかをビューセットが知るように、オブジェクトからシリアライザを動的にロードするスニペットがあります。私は数時間で私のPCに着くと、ここにアップロードします。 –

    0

    シリアライザに関する質問は2番目にありますが、まずは明確化のためです。 Workout/Finished Workout、Set/Finished Set ...などの重複モデルを持つ目的は何ですか?

    なぜそれが行わだとき...

    class Workout(models.Model): 
        #...stuff... 
        finished = models.DateTimeField(null=True, blank=True) 
        #...more stuff... 
    

    は次に、あなただけのワークアウトに完成した日付を設定することができません。

    今、質問について。ユーザーのやりとりについて考えることをお勧めします。フロントエンドのどの部分にデータを投入しようとしていますか?データはどのように関連しており、ユーザーはそのデータにどのようにアクセスしますか?

    DRFをどのようなパラメータでクエリしているのか考える必要があります。ただのその特定のタイプのためにあなたが好きなフィールドを持つことができます...そして、

    class FinishedWorkoutViewset(viewsets.GenericAPIView,mixins.ListModelMixin): 
        serializer_class = FinishedWorkOutSerializer 
        queryset = Workout.objects.all() 
        def list(self, request): 
         user = self.request.user 
         day = self.data['day']; 
         month = self.data['month']; 
         year = self.data['year']; 
         queryset = self.filter_queryset(self.get_queryset().filter(finished__date=datetime.date(year,month,day)).filter(user=user)) 
         page = self.paginate_queryset(queryset) 
         serializer = self.get_serializer(queryset, many=True) 
         return response.Response(serializer.data) 
    

    そして、あなたのFinishedWorkoutSerializer

    // This example is done in Angular, but you get the point... 
    var date= { 
        'day':'24', 
        'month':'10', 
        'year':'2015' 
    }; 
    API.finishedWorkout.query(date).$promise 
    .then(function(workouts){ 
        //...workouts is an array of workout objects... 
    }); 
    

    ビューセット:あなたは日付を送信してのトレーニングは、特定の日に終了した期待することができますクエリ。

    このように非常に特殊なURLがたくさん残っていますが、それほど優れているわけではありませんが、これらの相互作用には特定のシリアライザを使用でき、パラメタの種類に応じて動的にフィルタを変更できますself.data

    どのメソッドが呼び出されているか、アクティブなエクササイズだけをリストしたいと思っているかによって、フィルタリングする方法が異なる可能性がありますが、ユーザーが特定のエクササイズにクエリを行う場合は、 Exerciseオブジェクトにはmodels.BooleanField属性が「アクティブ」である必要があります)。

    class ExerciseViewset(viewsets.GenericViewSet, mixins.RetrieveModelMixin, mixins.ListModelMixin): 
        serializer_class = ExerciseSerializer 
        queryset = Exercise.objects.all() 
        def list(self, request): 
         queryset = self.filter_queryset(self.get_queryset().filter(active=True)) 
         page = self.paginate_queryset(queryset) 
         serializer = self.get_serializer(queryset, many=True) 
         return response.Response(serializer.data) 
    

    アクションによって、異なるURLに同じオブジェクトが表示されるようになりました。あなたが必要とするものにもう少し近いですが、まだ同じシリアライザを使用していますので、retrieve()に大きな入れ子オブジェクトが必要な場合は、list()のときにそれらの束を得ることになります。

    リストを短くして詳細をネストするには、別のシリアライザを使用する必要があります。

    あなたは彼らだけが一覧表示されたときに演習pkname属性を送信したいのですが、運動が照会されるたび、あなたは 『WorkoutSets』の配列の内側に命じ、関連するすべての 『設定』のオブジェクトに沿って送信するためにwan'tとしましょう...

    # Taken from an SO answer on an old question... 
    class MultiSerializerViewSet(viewsets.GenericViewSet): 
        serializers = { 
         'default': None, 
        } 
        def get_serializer_class(self): 
         return self.serializers.get(self.action, self.serializers['default']) 
    
    
    class ExerciseViewset(MultiSerializerViewSet, mixins.RetrieveModelMixin, mixins.ListModelMixin): 
        queryset = Exercise.objects.all() 
        serializers = { 
         'default': SimpleExerciseSerializer, 
         'retrieve': DetailedExerciseSerializer 
        } 
    

    次に、あなたのserializers.pyは、私はちょうどおそらくあなたのモデルに意味をなさないユースケースと属性の周りに投げてるような...

    #------------------Exercise 
    #--------------------------Simple List 
    class SimpleExerciseSerializer(serializers.ModelSerializer): 
        class Meta: 
         model Exercise 
         fields = ('pk','name') 
    
    #--------------------------Detailed Retrieve 
    class ExerciseWorkoutExerciseSetSerializer(serializers.ModelSerializer): 
        class Meta: 
         model Set 
         fields = ('pk','name','description') 
    
    class ExerciseWorkoutExerciseSerializer(serializers.ModelSerializer): 
        set_set = ExerciseWorkoutExerciseSetSerializer(many=True) 
        class Meta: 
         model WorkoutExercise 
         fields = ('pk','set_set') 
    
    class DetailedExerciseSerializer(serializers.ModelSerializer): 
        workoutExercise_set = exerciseWorkoutExerciseSerializer(many=True) 
        class Meta: 
         model Exercise 
         fields = ('pk','name','workoutExercise_set') 
    

    を少し見ることができるが、私はこれが役に立つと願っています。

    P.S .;最後にJavaがどのようになっているかを調べてください。p「ExcerciseServiceExcersiceBeanWorkoutFactoryFactoryFactory」

    関連する問題