2017-12-27 29 views
0

일부 속성을 계산하는 읽기 전용 필드가있는 모델이 있습니다. 쿼리 매개 변수에 따라보기에서 읽기 전용 필드의 값을 재정의하는 방법은 무엇입니까?

class BlastEvent(Event): 
    tonnes = models.FloatField() 
    blast_type = models.ForeignKey(BlastType) 

    @property 
    def size(self): 
     return self.tonnes/BlastEvent.objects.all().aggregate(Max('tonnes'))['tonnes__max'] 

내 시리얼입니다 :

class BlastEventSerializer(serializers.HyperlinkedModelSerializer): 

    size = serializers.ReadOnlyField() 

    included_serializers = {'blast_type': BlastTypeSerializer} 

    blast_type = ResourceRelatedField(
     queryset=BlastType.objects, 
     related_link_view_name='blastevent-blasttype-list', 
     related_link_url_kwarg='pk', 
     self_link_view_name='blastevent-relationships' 
    ) 

    class Meta: 
     model = BlastEvent 
     fields = ('url', 'id', 'tonnes', 'blast_type', 'size') 

    class JSONAPIMeta: 
     included_resources = ['blast_type'] 

그리고 이것은 내보기입니다 :

class BlastEventViewSet(EventViewSet): 
    queryset = BlastEvent.objects.all() 
    serializer_class = BlastEventSerializer 

가 지금은-계산을 다시하고 쿼리 매개 변수에 따라이 읽기 전용 필드를 재정의해야 . 나는 그것을 할 적절한 곳이 어디인지 잘 모르겠습니다. 내보기의 get_queryset() 메소드에서 다음과 같이 시도했다.

class BlastEventViewSet(EventViewSet): 
    queryset = BlastEvent.objects.all() 
    serializer_class = BlastEventSerializer 

    def get_queryset(self): 
     queryset = self.queryset 
     instrument_id = self.request.GET.get('instrument_id') 
     if instrument_id: 
      for e in queryset: 
       e.size = e.size + Instrument.objects.get(pk=instrument_id).distance 
     return queryset 

그러나 작동하지 않는다. '속성을 설정할 수 없습니다 AttributeError는'그것은 말한다 나는이 필드의 값을 대체 할 수 있습니다

Traceback: 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner 
    41.    response = get_response(request) 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response 
    187.     response = self.process_exception_by_middleware(e, request) 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response 
    185.     response = wrapped_callback(request, *callback_args, **callback_kwargs) 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view 
    58.   return view_func(*args, **kwargs) 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework/viewsets.py" in view 
    86.    return self.dispatch(request, *args, **kwargs) 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch 
    489.    response = self.handle_exception(exc) 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework/views.py" in handle_exception 
    449.    self.raise_uncaught_exception(exc) 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch 
    486.    response = handler(request, *args, **kwargs) 

File "/home/nargiza/virtualenvs/myenv/local/lib/python2.7/site-packages/rest_framework/mixins.py" in list 
    40.   queryset = self.filter_queryset(self.get_queryset()) 

File "/home/nargiza/Development/geotechnical-data-platform-api/events/views.py" in get_queryset 
    205.    e.size = ... 

가 쿼리 매개 변수에 따라?

답변

0

을 내가 생각 해낸 해결책은 to_representation() 직렬의 메소드를 오버라이드 (override)하는 것입니다

내가 수정할 수 있어야
def to_representation(self, instance): 
    ret = super(BlastEventSerializer, self).to_representation(instance) 

    instrument_id = self.context['request'].query_params.get('instrument_id') 
    if instrument_id: 
     ret['size'] = 77 # some custom calculations 
    return ret 
0

속성에는 할당을 위해 설정자가 필요합니다. 이 같은 BlastEvent에 세터를 추가하십시오 :

https://docs.python.org/3/library/functions.html#property

class BlastEvent(Event): 
    tonnes = models.FloatField() 
    blast_type = models.ForeignKey(BlastType) 

    def _get_size(self): 
     return self.tonnes/BlastEvent.objects.all().aggregate(Max('tonnes'))['tonnes__max'] 

    @property 
    def size(self): 
     if callable(self._get_size): 
      return self._get_size() 
     else: 
      return self._get_size 

    @size.setter 
    def size(self, value): 
     self._get_size = value 
+0

이 필드는 쿼리 매개 변수에 따라 수정해야하기 때문에 뷰에서. – NST

+0

맞음 - setter 메서드를 사용하면 인스턴스화 된 BlastEvent의 크기 특성을 수정할 수 있다고 생각합니다. 이 솔루션이 작동하지 않습니까? 왜? – whp