2013-11-24 10 views
5

kullanarak iç içe nesneye geri dön Bazı API uç noktalarını açığa çıkarmak için DRF kullanıyorum.Django Rest Framework, NestKeyRelatedField

# models.py 

class Project(models.Model): 
    ... 
    assigned_to = models.ManyToManyField(
     User, default=None, blank=True, null=True 
    ) 



# serializers.py 

class ProjectSerializer(serializers.ModelSerializer): 
    assigned_to = serializers.PrimaryKeyRelatedField(
     queryset=User.objects.all(), required=False, many=True) 

    class Meta: 
     model = Project 
     fields = ('id', 'title', 'created_by', 'assigned_to') 


# view.py 

class ProjectList(generics.ListCreateAPIView): 
    mode = Project 
    serializer_class = ProjectSerializer 
    filter_fields = ('title',) 

    def post(self, request, format=None): 
     # get a list of user.id of assigned_to users 
     assigned_to = [x.get('id') for x in request.DATA.get('assigned_to')] 
     # create a new project serilaizer 
     serializer = ProjectSerializer(data={ 
      "title": request.DATA.get('title'), 
      "created_by": request.user.pk, 
      "assigned_to": assigned_to, 
     }) 
     if serializer.is_valid(): 
      serializer.save() 
     else: 
      return Response(serializer.errors, 
         status=status.HTTP_400_BAD_REQUEST) 
     return Response(serializer.data, status=status.HTTP_201_CREATED) 

Her şey düzgün çalışıyor ve alana atanan kimliğin listesini listeleyebilirim. Ancak, bu işlevi yapmak için RelatedField yerine PrimaryKeyRelatedField kullanmak zorunda kaldım. Bu, GET yaptığımda, yalnızca kullanıcının birincil anahtarlarını assigned_to alanına aldığım anlamına gelir. POST için geçerli davranışı sürdürmenin bir yolu var, ancak assigned_to alanı için seri hale getirilmiş User ayrıntılarını döndürüyor musunuz?

cevap

3

Bu durumda POST ve GET için farklı bir sayısallaştırıcı kullanmanız gerekir.

Görünümde get_serializer_class() yöntemini geçersiz kılmaya ve self.request.method'a bağlı olarak iade edilen seri hale getiriciyi değiştirmeye göz atın.

+0

Yani, get_serializer_class() yöntemini geçersiz çalıştı: 'def get_serializer_class (self): Baskı self.request.method; eğer self.request.method == "GET": ... 'ama istek her zaman" GET ", koşucuda bir" POST "görsem bile. –

2

Son zamanlarda bunu, değeri ayarlamak için giriş için kimlik kullanan, ancak serileştiricileri kullanarak bir yuvalanmış değer döndüren bir alt sınıf PrimaryKeyRelatedField() ile çözdüm. Şimdi bu burada istenen% 100 olmayabilir. POST, PUT ve PATCH yanıtları da iç içe geçmiş gösterimi içerecek, ancak soru POST'un bir PrimaryKeyRelatedField ile tam olarak aynı şekilde davranacağını belirtecektir.

https://gist.github.com/jmichalicek/f841110a9aa6dbb6f781

class PrimaryKeyInObjectOutRelatedField(PrimaryKeyRelatedField): 
    """ 
    Django Rest Framework RelatedField which takes the primary key as input to allow setting relations, 
    but takes an optional `output_serializer_class` parameter, which if specified, will be used to 
    serialize the data in responses. 

    Usage: 
     class MyModelSerializer(serializers.ModelSerializer): 
      related_model = PrimaryKeyInObjectOutRelatedField(
       queryset=MyOtherModel.objects.all(), output_serializer_class=MyOtherModelSerializer) 

      class Meta: 
       model = MyModel 
       fields = ('related_model', 'id', 'foo', 'bar') 

    """ 

    def __init__(self, **kwargs): 
     self._output_serializer_class = kwargs.pop('output_serializer_class', None) 
     super(PrimaryKeyInObjectOutRelatedField, self).__init__(**kwargs) 

    def use_pk_only_optimization(self): 
     return not bool(self._output_serializer_class) 

    def to_representation(self, obj): 
     if self._output_serializer_class: 
      data = self._output_serializer_class(obj).data 
     else: 
      data = super(PrimaryKeyInObjectOutRelatedField, self).to_representation(obj) 
     return data