代码之家  ›  专栏  ›  技术社区  ›  Omar Jandali

Django Rest Framework视图集正在返回选定的记录,而不是列表视图中的所有记录

  •  0
  • Omar Jandali  · 技术社区  · 6 年前

    我有一个django应用程序。我的应用程序中有一部分无法正常工作。到目前为止,我正在使用django rest框架视图集。我想要的是两个基本上在同一个视图集中有两个不同的列表视图。1返回accountviewset中的所有帐户,另一个列表视图根据帐户模型中的用户foreignkey返回与用户关联的所有帐户。

    下面的代码返回与特定人员关联的所有帐户,但我无法使用列表视图返回数据库中的所有帐户。

    class AccountViewSet(viewsets.ModelViewSet):
        serializer_class = AccountSerializer
        queryset = Account.objects.all()
        lookup_field = 'user__username'
    
        def list(self, request):
            queryset = Account.objects.all()
            serializer_class = AccountSerializer
    
            def get_object(self):
                return self.queryset.get(user__username=self.kwargs.get('username'))
    

    class AccountViewSet(viewsets.ModelViewSet):
        queryset = Account.objects.all();
        serializer_class = AccountSerializer
        filter_backends = (filters.DjangoFilterBackend,)
        filterset_fields = ('user', 'name', '_class')
        lookup_field = 'user__username'
    
        # def get_queryset(self):
        #     return self.queryset.filter(user__username=self.kwargs.get('username'))
    

    当有一个帐户与一个用户关联时,它工作。 无法处理2个以上的帐户,错误为:

    MultipleObjectsReturned at /api/users/accounts/omarjandali/
    get() returned more than one Account -- it returned 2!
    

    其他尝试不会返回端点中有特定用户或没有用户的任何帐户。

    最大的问题是,它返回的是用户id,而不是用户用户名。

    enter image description here

    当前代码:

    serializers.py:

    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('username', 'first_name', 'last_name', 'email', 'is_staff')
    
    class ProfileSerializer(serializers.ModelSerializer):
        class Meta:
            model = Profile
            fields = ('user', 'gender', 'phone', 'ip_address', 'dob_month', 'dob_day',
                      'dob_year', 'address_street', 'address_city', 'address_state',
                      'address_postal', 'address_country', 'profile_pic', 'role')
    
    class FriendSerializer(serializers.ModelSerializer):
        class Meta:
            model = Friend
            fields = ('requested', 'friended', 'status', 'blocked')
    
    class AccountSerializer(serializers.ModelSerializer):
        user = UserSerializer(
            read_only = True,
        )
    
        class Meta:
            model = Account
            fields = ('user', '_id', 'name', 'balance', 'currency', 'bank_name',
                      'routing', '_class', 'type', 'active', 'main', 'synapse')
    

    Views.py:

    class UserViewSet(viewsets.ModelViewSet):
        serializer_class = UserSerializer
        queryset = User.objects.all()
        lookup_field = 'username'
    
    class ProfileViewSet(viewsets.ModelViewSet):
        serializer_class = ProfileSerializer
        queryset = Profile.objects.all()
        lookup_field = 'user__username'
    
    class FriendViewSet(viewsets.ModelViewSet):
        serializer_class = FriendSerializer
        querset = Friend.objects.all()
        lookup_field = 'user__username'
    
    class AccountViewSet(viewsets.ModelViewSet):
        queryset = Account.objects.all();
        serializer_class = AccountSerializer
        filter_backends = (filters.DjangoFilterBackend,)
        filter_fields = ('user',)
    

    网址:

    from rest_framework.routers import DefaultRouter
    
    router = DefaultRouter()
    router.register(r'users', UserViewSet, basename='user')
    router.register(r'profiles', ProfileViewSet, basename='profile')
    router.register(r'friends', FriendViewSet, basename='friend')
    router.register(r'accounts', AccountViewSet, basename='account')
    urlpatterns = router.urls
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Ken4scholars    6 年前

    首先,您的代码有很多问题。如果需要返回列表,则应在 get_object 方法它意味着只返回一个实例,所以在 get_queryset get_object() 在您的列表方法中,这是错误的。第三,在list方法中分配序列化器类没有意义。它甚至在调用该方法之前就被赋值了。

    现在回到您的问题,“列表”是一个视图集操作,您不能执行两次。相反,您可以添加一个 extra action 为此,只需在viewset的action方法中添加一个方法。

    在您的特殊情况下,我会这样做:我将引入一个实例变量, qs_type 用于控制由 get_queryset() 方法

    大概是这样的:

    def __init__(self, *args, **kwargs):
        self.qs_type = 'user_only'
        super().__init__(*args, **kwargs)
    
    def get_queryset(self):
        if self.qs_type == 'user_only':
            qs = Account.objects.filter(username=self.kwargs.get('username'))
        else:
            qs = Account.objects.all()
        return qs)
    
    
    @action(detail=False, methods=['get'])
    def all(self, request, *args, **kwargs):
        self.qs_type = 'all'
        return self.list(request, *args, **kwargs)
    

    这假定在默认情况下,将返回用户名筛选版本,而在新操作中将返回所有帐户。你可以 qs_型