如何根据查询参数覆盖视图中readonly字段的值?

2024-04-26 07:07:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个模型,它有一个只读字段,我在其中计算一些属性。你知道吗

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\u 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 = ...

在哪里可以根据查询参数覆盖此字段的值?你知道吗


Tags: inpyselfhomegetlibpackageslocal
2条回答

属性需要设置器进行赋值。尝试向BlastEvent添加setter,如下所示:

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

我提出的解决方案是重写序列化程序的\u representation()方法:

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

相关问题 更多 >