2017-07-21 8 views
1

ネストされたシリアライザを使用しようとしています。ルートシリアライザを使用して孫シリアライザのデータをフィルタするにはどうすればよいですか?DRFのネストシリアライザ - 子シリアライザのデータのフィルタリング

学校とプログラムには多種多様な関係があり、あらゆる学校がどのプログラムにも加入できるようになっています。各学校にはクラスがあり、そのクラスはプログラムの一部です。そのため、PClassは学校とプログラムの両方に外部キーを持っています。

私は学校が加入すると、クラスは(その学校で)各プログラムで利用可能であることを、すべてのプログラムを取得したい.../API /学校/ 1私のAPIを呼び出す

class School(TimeStampedModel, SoftDeletableModel): 
    name = models.CharField(max_length=40) 
    slug = models.SlugField(max_length=40, default='', blank=True) 

class Program(TimeStampedModel, SoftDeletableModel): 
    name = models.CharField(max_length=50, unique=True) 
    slug = models.SlugField(max_length=50,default='',blank=True, unique=True) 
    description = models.CharField(max_length=100, blank=True) 
    school = models.ForeignKey(School, blank=True, null=True, related_name="programs") 

class PClass(TimeStampedModel, SoftDeletableModel): 
    name = models.CharField(max_length=50) 
    slug = models.SlugField(max_length=50,default='',blank=True) 
    description = models.CharField(max_length=100) 
    program = models.ForeignKey(Program, related_name="classes") 
    school = models.ForeignKey(School, related_name="classes") 

と次のシリアライザ:

class SchoolSerializer(serializers.ModelSerializer): 
    programs = ProgramSerializer(source='get_programas',many=True,read_only=True) 
    class Meta: 
     model = School 
     fields = '__all__' 
     lookup_field = 'slug' 
     extra_kwargs = { 
      'url': {'lookup_field': 'slug'} 
     } 

class PClassSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Class 
     fields = ('name','slug') 

class ProgramSerializer(serializers.ModelSerializer): 
    school = serializers.SlugRelatedField(queryset=School.objects.all(), 
              slug_field='name', 
              required=False) 
    classes = PClassSerializer(many=True,read_only=True) 
    class Meta: 
     model = Program 
     exclude = ('id',) 
     lookup_field = 'slug' 
     extra_kwargs = { 
      'url': {'lookup_field': 'slug'} 
     } 

これは可能ですか?それとも私のモデルをセットアップする方法に問題がありますか?

答えて

2

これを行う方法は2通りあります。最初はあなたはすでにかなり近いです。 EDIT:関連する名前を使用していることに気付きました。私は最善の方法は、SerializerMethodFieldフィールドを使用することです、より複雑なフィルタリングのためにその

​​

のための答えを更新しました。ここに例があります。

クエリの数を最小限に抑えるためにクエリセットを取得するために、プリフェッチをいくつか行うこともできます。

class SchoolSerializer(serializers.ModelSerializer): 
    programas = SerializerMethodField(source='get_programas',many=True,read_only=True) 
    class Meta: 
     model = Unidade 
     fields = '__all__' 
     lookup_field = 'slug' 
     extra_kwargs = { 
      'url': {'lookup_field': 'slug'} 
     } 

    def get_programas(self, obj): 
     # You can do more complex filtering stuff here. 
     return ProgramaSerializer(obj.programs.all(), many=True, read_only=True).data 

あなただけProgramSerializerため

program.classes.filter(school=program.school) 

全例で、あなたのクエリセットをフィルタリングする必要がありますPClassesを取得するには、そう

class ProgramSerializer(serializers.ModelSerializer): 
    classes = SerializerMethodField(source='get_classes', many=True, read_only=True) 
    class Meta: 
     model = Program 

    def get_classes(self, obj): 
     return PClassSerializer(obj.classes.filter(school=obj.school), many=True, read_only=True).data 

EDIT 10以上であります

プログラム - >スクールを外部キーからManyToMany、これはすべてを変更します。

学校のシリアライザでは、SerializerMethodFieldを使用する必要があります。この方法で、contextを入れ子になったシリアライザに渡すことができます。

class SchoolSerializer(serializers.ModelSerializer): 
    classes = SerializerMethodField(source='get_programs') 
    class Meta: 
     model = School 

    def get_programs(self, obj): 
     return ProgramSerializer(obj.program_set.all(), many=True, read_only=True, context={ "school": obj }).data 

class ProgramSerializer(serializers.ModelSerializer): 
    classes = SerializerMethodField(source='get_classes', many=True, read_only=True) 
    class Meta: 
     model = Program 

    def get_classes(self, obj): 
     return PClassSerializer(obj.classes.filter(school=self.context["school"]), many=True, read_only=True).data 
+0

PCSerializerでシリアル化されているスクールのクラスのみを表示するにはどうすればよいですか? – JLugao

+0

私の答えの一番下に追加されました。 – jonzlin95

+0

しかし、program.schoolはこのプログラムに登録されているすべての学校のリストを返すでしょうか?または私は何かを逃していますか? – JLugao

関連する問題