当我想使用get_serializer_class()根据url参数为不同的用户返回不同的字段时,django-rest-swagger不起作用

时间:2022-05-18 02:52:31

I am using django-rest-swagger for api doc generation. I would like to return different user the different part of models. So I used the get_serializer_class() function to use different serializer for different users by checking the kwargs['pk'] on the url.

我正在使用django-rest-swagger来生成api doc。我想向不同的用户返回不同的模型部分。所以我使用get_serializer_class()函数通过检查url上的kwargs ['pk']为不同的用户使用不同的序列化器。

The urls.py is:

urls.py是:

url(r'^api/users/$', views.UserEnum.as_view()),
url(r'^api/users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),

The view that I am using is:

我使用的观点是:

#List all the users or create a new user
class UserEnum(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAuthenticated, IsAdminUser,)

class UserDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    #serializer_class = UserSerializer #TODO: Problem with Swagger
    permission_classes = (IsAuthenticated, IsOwnerAdminOrReadOnly,)

    def get_serializer_class(self):
        #swagger crash here.
        user_id = int(self.kwargs['pk'])
        if self.request.user.id == user_id or self.request.user.is_superuser:
            serializer_class = UserSerializer
        else:
            serializer_class = UserProfileSerializer
        return serializer_class

    def get_object(self, *args, **kwargs):
        user_id = int(self.kwargs['pk'])

        if self.request.user.id == user_id or self.request.user.is_superuser:
            return User.objects.get(id=user_id)
        else:
            return UserProfile.objects.get(user=user_id)

The serializer classes I am using are:

我使用的序列化程序类是:

class UserProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserProfile
        fields = ('photo', 'description', 'birthday', 'credit',)

class UserSerializer(serializers.ModelSerializer):
    profile = UserProfileSerializer()

    class Meta:
        model = User
        fields = ('id', 'last_login', 'username', 'email', 'date_joined', 'profile', )
        ...

The UserProfile is:

UserProfile是:

class UserProfile(models.Model):
    user = models.OneToOneField(User, primary_key=True, related_name="profile")
    photo = models.ImageField(upload_to='user_photo', null=True, blank=True)
    description = models.TextField(blank=True)
    birthday = models.DateTimeField(blank=True)
    credit = models.PositiveIntegerField()

    def __unicode__(self):
        return u'%s' % (self.user.username)

The above two urls work successfully without problems. (Or anyone can tell me The right way of returning different fields for different users based on the url parameters? ) But when I type the http://127.0.0.1:8000/api/ for generate api docs, it return the below error:

以上两个网址成功运行没有问题。 (或者任何人都可以告诉我基于url参数为不同用户返回不同字段的正确方法?)但是当我输入http://127.0.0.1:8000/api/生成api文档时,它会返回以下错误:

Unable to read api 'users' from path http://127.0.0.1:8000/api/api-docs/api/users (server returned Internal Server Error)

无法从路径http://127.0.0.1:8000/api/api-docs/api/users读取api'用户'(服务器返回内部服务器错误)

So I test the http://127.0.0.1:8000/api/api-docs/api/users alone, and I get the error tips with more details:

所以我单独测试了http://127.0.0.1:8000/api/api-docs/api/users,我得到了更多细节的错误提示:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/api/api-docs/api/users

Django Version: 1.6.5
Python Version: 2.7.8
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'south',
 'rest_framework',
 'rest_framework_swagger',
 'django_extensions',
 '***')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')


Traceback:
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  112.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
  57.         return view_func(*args, **kwargs)
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/django/views/generic/base.py" in view
  69.             return self.dispatch(request, *args, **kwargs)
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  407.             response = self.handle_exception(exc)
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  404.             response = handler(request, *args, **kwargs)
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework_swagger/views.py" in get
  119.             'apis': generator.generate(apis),
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework_swagger/docgenerator.py" in generate
  32.                 'operations': self.get_operations(api, apis),
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework_swagger/docgenerator.py" in get_operations
  68.             serializer = self._get_method_serializer(method_introspector)
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework_swagger/docgenerator.py" in _get_method_serializer
  165.         serializer = method_inspector.get_response_serializer_class()
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework_swagger/introspectors.py" in get_response_serializer_class
  203.             serializer = self.get_serializer_class()
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework_swagger/introspectors.py" in get_serializer_class
  196.             serializer = self.ask_for_serializer_class()
File "/Users/Scofield/anaconda/lib/python2.7/site-packages/rest_framework_swagger/introspectors.py" in ask_for_serializer_class
  179.                 return view.get_serializer_class()
File "/Users/Scofield/Dropbox/My Projects/Angels&Demons/src/doWishSites/doWishCore/views.py" in get_serializer_class
  27.         user_id = int(self.kwargs['pk'])

Exception Type: KeyError at /api/api-docs/api/users
Exception Value: 'pk'

1 个解决方案

#1


0  

Try raping your code that accesses self.kwargs['pk'] with a try and except block

尝试强制使用try和except块访问self.kwargs ['pk']的代码

   def get_serializer_class(self):
        # swagger crash here.
        try:
            user_id = int(self.kwargs['pk'])
        except Exception as e:
            print(e)
        if self.request.user.id == user_id or self.request.user.is_superuser:
            serializer_class = UserSerializer
        else:
            serializer_class = UserProfileSerializer
        return serializer_class

Source https://github.com/marcgibbons/django-rest-swagger/issues/194

来源https://github.com/marcgibbons/django-rest-swagger/issues/194

#1


0  

Try raping your code that accesses self.kwargs['pk'] with a try and except block

尝试强制使用try和except块访问self.kwargs ['pk']的代码

   def get_serializer_class(self):
        # swagger crash here.
        try:
            user_id = int(self.kwargs['pk'])
        except Exception as e:
            print(e)
        if self.request.user.id == user_id or self.request.user.is_superuser:
            serializer_class = UserSerializer
        else:
            serializer_class = UserProfileSerializer
        return serializer_class

Source https://github.com/marcgibbons/django-rest-swagger/issues/194

来源https://github.com/marcgibbons/django-rest-swagger/issues/194