djangorestframework метод 'PUT' / 'PATCH' не работает - PullRequest
0 голосов
/ 26 апреля 2018

Я довольно новичок в DRF и FK и пытаюсь сделать 'PUT' / 'PATCH' для приложения, но пока безуспешно.Остальные операции CRUD работают нормально.Есть элемент FK, который, я думаю, вызывает проблемы для этой конкретной операции.Как мне получить обновление - функция 'PUT' / 'PATCH' собирается здесь?Ваша помощь будет принята с благодарностью - Заранее большое спасибо:)

Вот соответствующие фрагменты -

models.py

    from django.db import models

# Create your models here.


class House(models.Model):
    house = models.CharField(max_length=50)
    parent_house = models.ForeignKey('self', related_name='base_house',
                           blank=True, null=True, on_delete=models.CASCADE)
    attributes = models.ManyToManyField('HouseAttributes',
                                        through='HouseAttributesMapping')

    class Meta:
        db_table = 'sku'

    def __str__(self):
        return "%s" % self.sku


class HouseAttributes(models.Model):
    house_attribute = models.CharField(max_length=50, unique=True)

    class Meta:
        db_table = 'house_attributes'

    def __str__(self):
        return "%s" % self.house_attribute


class HouseAttributesMapping(models.Model):
    house = models.ForeignKey(House, on_delete=models.CASCADE)
    house_attribute = models.ForeignKey(HouseAttributes, on_delete=models.CASCADE)
    value = models.CharField(max_length=50)

    class Meta:
        db_table = 'house_attributes_mapping'

views.py

from .models import House, HouseAttributes, HouseAttributesMapping
from serializers.skuSerializer import HouseListSerializer, HouseDetailSerializer

from rest_framework import generics, mixins
from rest_framework import viewsets

# Create your views here.

class HouseListApi(mixins.ListModelMixin, mixins.CreateModelMixin,
                 generics.GenericAPIView):
    queryset = House.objects.all()
    serializer_class = HouseListSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class HouseDetailApi(generics.RetrieveUpdateDestroyAPIView):
    queryset = House.objects.all()
    serializer_class = HouseDetailSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


class HouseViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.
    """
    queryset = House.objects.all()
    serializer_class = HouseListSerializer

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

И Сериализаторы, где я внес изменения - "обновление по умолчанию" под CowDetailSerializer

   from rest_framework import serializers
from apps.skus.models import House, HouseAttributes, HouseAttributesMapping

class HouseAttributesSerializer(serializers.ModelSerializer):
    class Meta:
        model = HouseAttributes
        fields = ("house_attribute",)


class HouseAttributesMappingSerializer(serializers.ModelSerializer):
    house_attribute = serializers.ReadOnlyField(
        source='house_attribute.sku_attribute')

    class Meta:
        model = HouseAttributesMapping

        fields = ('house_attribute', 'value')
        order_by = ('house_attribute')


class ParentHouseSerializer(serializers.ModelSerializer):
    parent_detail = serializers.HyperlinkedIdentityField(
        view_name='house_detail_api', lookup_field="pk")
    class Meta:
        model = House
        fields = ("id", "house", "parent_detail")


class HouseDetailSerializer(serializers.ModelSerializer):
    queryset = HouseAttributes.objects.all()
    house_attributes = HouseAttributesMappingSerializer(
        source='houseattributesmapping_set', many = True)
    class Meta:
        model = House
        depth = 1
        fields = ("house", "house_attributes")


    def update(self, validated_data, kwargs={}):
        house_value = self.data['house']
        house = {'house': house_value}
        houSe = House.objects.get_or_create(**self.data.house_attributes)

        return data


import ast

class HouseListSerializer(serializers.HyperlinkedModelSerializer):
    detail = serializers.HyperlinkedIdentityField(view_name='house_detail_api',
                                                  lookup_field="pk")

    parent_house = serializers.StringRelatedField()

    class Meta:
        model = House
        fields = ("house", "detail", "parent_house")

        def create(self, validated_data, kwargs={}):
            house_detail = self.objects.create(**validated_data)
            house = House.objects.get_or_create(house_detail)[0]['sku']

            return house

Когда я пытаюсь обновить форму напользовательский интерфейс с приведенным выше кодом «def update» в «CowDetailSerializer», это ошибка, которую я получаю - я разместил полный трассировку с локальными переменными, извлеченными в последней строке.

    AttributeError at /list/1/
'ReturnDict' object has no attribute 'sku_attributes'
Request Method: PUT
Request URL:    http://localhost:8000/list/1/
Django Version: 2.0.4
Exception Type: AttributeError
Exception Value:    
'ReturnDict' object has no attribute 'house_attributes'
Exception Location: /home/Downloads/transcend/serializers/houseSerializer.py in update, line 74
Python Executable:  /home/anaconda3/envs/transcend/bin/python
Python Version: 3.6.5
Python Path:    
['/home/Downloads/transcend',
 '/home/anaconda3/envs/transcend/lib/python36.zip',
 '/home/anaconda3/envs/transcend/lib/python3.6',
 '/home/anaconda3/envs/transcend/lib/python3.6/lib-dynload',
 '/home/anaconda3/envs/transcend/lib/python3.6/site-packages']
Server time:    Wed, 25 Apr 2018 21:08:40 +0000
Traceback Switch to copy-and-paste view
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/django/core/handlers/exception.py in inner
            response = get_response(request) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/django/core/handlers/base.py in _get_response
                response = self.process_exception_by_middleware(e, request) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/django/core/handlers/base.py in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/django/views/decorators/csrf.py in wrapped_view
        return view_func(*args, **kwargs) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/django/views/generic/base.py in view
            return self.dispatch(request, *args, **kwargs) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/rest_framework/views.py in dispatch
            response = self.handle_exception(exc) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/rest_framework/views.py in handle_exception
            self.raise_uncaught_exception(exc) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/rest_framework/views.py in dispatch
            response = handler(request, *args, **kwargs) ...
▶ Local vars
/home/Downloads/transcend/apps/skus/views.py in put
        return self.update(request, *args, **kwargs) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/rest_framework/mixins.py in update
        self.perform_update(serializer) ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/rest_framework/mixins.py in perform_update
        serializer.save() ...
▶ Local vars
/home/anaconda3/envs/transcend/lib/python3.6/site-packages/rest_framework/serializers.py in save
            self.instance = self.update(self.instance, validated_data) ...
▶ Local vars
/home/Downloads/transcend/serializers/houseSerializer.py in update
        houSe = House.objects.get_or_create(**self.data.sku_attributes) ...
▼ Local vars
Variable    Value
kwargs  
{'house': 'CXA-03070-B110',
 'houseattributesmapping_set': [OrderedDict([('value',
                                            'CXccccccccccccccccccccccccccccccc3070H')]),
                              OrderedDict([('value', 'HIGH')]),
                              OrderedDict([('value', 'rbtsh8_6_3-nic1')]),
                              OrderedDict([('value', 'LDB')])]}
self    
HouseDetailSerializer(<House: CXA-03070-B110>, context={'request': <rest_framework.request.Request object>, 'format': None, 'view': <apps.house.views.houseDetailApi object>}, data={'house': 'CXA-03070-B110', 'house_attributes': [{'house_attribute': 'model', 'value': 'CXccccccccccccccccccccccccccccccc3070H'}, {'house_attribute': 'mclass', 'value': 'HIGH'}, {'house_attribute': 'preconfig', 'value': 'rbtsh8_6_3-nic1'}, {'house_attribute': 'serial_prefix', 'value': 'LDB'}]}, partial=False):
    house = CharField(max_length=50)
    house_attributes = HouseAttributesMappingSerializer(many=True, source='houseattributesmapping_set'):
        house_attribute = ReadOnlyField(source='house_attribute.house_attribute')
        value = CharField(max_length=50)
house   
{'house': 'CXA-03070-B110'}
house_value 
'CXA-03070-B110'
validated_data  
<House: CXA-03070-B110>

1 Ответ

0 голосов
/ 26 апреля 2018

Вместо self.data используйте cleaned_data в методе update.Кроме того, поскольку cleaned_data является диктом, вы должны получить синтаксис hous_attributes через get(), а не с ., например:

def update(self, validated_data, kwargs={}):
    house_value = validated_data['house']
    house = {'house': house_value}
    houSe = House.objects.get_or_create(**validated_data.get('house_attributes'))

    return houSe
...