将参数从视图传递到Custom RelatedField序列化程序

时间:2015-10-12 09:49:22

标签: django-rest-framework

如何将参数传递给来自views.py的serializers.RelatedField类。我需要传递language_id来查询那个RelatedField中的Language.objects模型。

我不确定我是否对此问题采取了正确的方法。我想要实现的是根据语言从数据库模型中呈现与电影相关的类型的信息。 MovieGenre模型有类型ID字段,我想用实际的类型名称替换。

我的serialiser.py

i_max= 3;
u = zeros(4,5,13);
a1 = 1;
a2 = 1;
a3 = 1;
b1 = 1;
hx = linspace(1D-6,1D6,13); // 1 x 13
ht = linspace(1D-6,1D6,13); // 1 x 13

for i = 1:i_max
    for j = 2:4
        u(i+1,j,:)= u(i,j)... 
                  + ht*(a1*u(i,j))*b1... // 1 x 13 
                  +(((a2*u(i,j+1)) -(2*a2*u(i,j)) +(a2*u(i,j-1)))*(hx.^-2))... // 1 x 13 
                  +(((a3*u(i,j+1))-(a3*u(i,j-1)))*(0.5*hx.^-1)) ... // 1 x 13   
                  + hx*ones(13,1)*ht; // added to get non-zero values
                  z = squeeze( u(i+1,j, : ))'; // 1x13

                  // for a 3d-plot: (1x13, 1x13, 13x13) 
                  figure()
                  plot3d(ht,hx, z'* z ,'*' ); //

    end
end

如您所见,这里我使用默认值查询Language.objects,但我想从视图(language_id)传递它。

我的views.py:

class GenreField(serializers.RelatedField):
    def to_representation(self, value, language_id=1):
        genre_name = GenresVideo.objects.get(genre_id=value, language_id=language_id)
        return genre_name.name

class MovieGenresSerializer(serializers.ModelSerializer):
    genre_id = GenreField(read_only=True)

    class Meta:
        model = MoviesGenres

我的urls.py:

class MovieGenresTestViewSet(viewsets.ModelViewSet):
    lookup_field = 'movie'
    queryset = MoviesGenres.objects.all()
    serializer_class = MovieGenresSerializer

    def list(self, request, language_pk):
        queryset = MoviesGenres.objects.all()
        serializer = MovieGenresSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, movie, language_pk):
        queryset = MoviesGenres.objects.filter(movie=movie)
        serializer = MovieGenresSerializer(queryset, many=True)
        return Response(serializer.data)

我的models.py

router.register(r'lang', LanguagesViewSet, base_name='lang')
mov_gen = routers.NestedSimpleRouter(router, r'lang', lookup='language')
mov_gen.register(r'mg', MovieGenresTestViewSet, base_name='mg')
url(r'^api/', include(genre_spec.urls))

通过urls路由,我可以从API获得正确的响应,包括language_id。我只需要以某种方式将它传递给视图。

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我会尝试回答您的第一个问题,并尽可能简化实施:SerializerMethodField。因为我们将通过传递给序列化程序的上下文获取语言ID,所以我们应该为序列化器生成上下文,或者让框架为我们做这个。

现在问题就在于:您没有按语言本身过滤查询集(MoviesGenres)。因此,我们可以避免覆盖列表和检索方法。尽管如此,路由器机制会在kwargs中为view方法注入language_pk参数 - 这是我们将在序列化器上下文中检索的参数:

class MovieGenresSerializer(serializers.ModelSerializer):
    genre = searializers.SerializerMethodField()

    class Meta:
        model = MoviesGenres

    def get_genre(self, instance):
        # get the language id from the view kwargs
        language_id = self.context['view'].kwargs['language_pk']
        # get the genre
        try:
            genre_name = GenresVideo.objects.get(genre_id=instance.genre_id, language_id=language_id).name
        except GenresVideo.DoesNotExist:
            genre_name = None
        # return the formatted output
        return genre_name


class MovieGenresTestViewSet(viewsets.ModelViewSet):
    lookup_field = 'movie'
    queryset = MoviesGenres.objects.all()
    serializer_class = MovieGenresSerializer