Django_rest_framwork "TypeError: Link object does not support element assignment"

Project using Django, DRF, swagger.

URL below:

schema_view = get_swagger_view(title='Pastebin API')
urlpatterns = [
    url(r'^$', schema_view),
    url(r'store', include('store.urls')),
    ... # other urls using routers.SimplerRouter
]

      

and store / urls.py:

router = routers.SimpleRouter()
router.register(r'', views.StoreViewSet)
urlpatterns = router.urls

      

and views.StoreViewSet:

class StoreViewSet(BaseObject, GenericViewSet):
    permition_class = ()

    @list_route()
    def detail(self, request):
        return {}

    @list_route(url_path='detail/export')
    def detail_export(self, request):
        return {}

      

after python manage.py runserver

, visit http://127.0.0.1:8000/#

and typeError occurred:

File "/usr/local/share/.virtualenvs/dev-finance/lib/python2.7/site-packages/rest_framework_swagger/views.py", line 32, in get
schema = generator.get_schema(request=request)
File "/usr/local/share/.virtualenvs/dev-finance/lib/python2.7/site-packages/rest_framework/schemas.py", line 242, in get_schema
links = self.get_links(request)
File "/usr/local/share/.virtualenvs/dev-finance/lib/python2.7/site-packages/rest_framework/schemas.py", line 276, in get_links
insert_into(links, keys, link)
File "/usr/local/share/.virtualenvs/dev-finance/lib/python2.7/site-packages/rest_framework/schemas.py", line 79, in insert_into
target[keys[-1]] = value
TypeError: 'Link' object does not support item assignment
[ERROR] 2017-05-04 15:25:06,936 log_message(basehttp.py:131) "GET / HTTP/1.1" 500 20384

      

The error message indicates that the object Link

cannot assign a value such as dict.

If I rename the method name from detail_export

to details_export

, everything is fine.

A guessing error occurred when the decor_framework @list_route

decorater passed the url method for the Link object.

why are other methods just fine? how can i solve this?

+3


source to share


2 answers


This is a bug in DRF . This will probably be fixed in 3.6.4. Now you can:



  • Remove url_path

    from list_route

    :

    class StoreViewSet(BaseObject, GenericViewSet):
        permition_class = ()
    
        @list_route()
        def detail(self, request):
            return {}
    
        @list_route()
        def detail_export(self, request):
            return {}
    
          

  • Or use custom SchemaView

    with custom SchemaGenerator

    :

    # api/schema.py for example
    
    from rest_framework.permissions import AllowAny
    from rest_framework.renderers import CoreJSONRenderer
    from rest_framework.response import Response
    from rest_framework.schemas import SchemaGenerator
    from rest_framework.views import APIView
    from rest_framework_swagger import renderers
    
    
    class CustomSchemaGenerator(SchemaGenerator):
        def get_keys(self, subpath, method, view):
            result = super().get_keys(subpath, method, view)
            # here you can fix your path
            if result == ['store', 'detail', 'detail_export']:  
                return ['store', 'detail_export'] 
            return result
    
    
    class SwaggerSchemaView(APIView):
        _ignore_model_permissions = True
        exclude_from_schema = True
        permission_classes = [AllowAny]
        renderer_classes = [
            CoreJSONRenderer,
            renderers.OpenAPIRenderer,
            renderers.SwaggerUIRenderer
        ]
    
        def get(self, request):
            generator = CustomSchemaGenerator(title='API')
            return Response(generator.get_schema(request=request))
    
    # urls.py
    
    from django.contrib.auth.decorators import login_required
    from api.schema import SwaggerSchemaView   
    
    urlpatterns = [
        # ...
        url(r'^swagger-url/', login_required(SwaggerSchemaView.as_view()))
        # ...
    ]
    
          

+2


source


Here's a hack:

  • Open your-environment-folder / Library / python3.5 / site-packages / rest_framework / schemas.py
  • Find function "insert_into"
  • Replace this:

    target[keys[-1]] = value
    
          



with this:

if type(target) != coreapi.Link:
    target[keys[-1]] = value

      

0


source







All Articles