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

时间:2019-01-27 21:38:34

标签: django django-rest-framework

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

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

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 个答案:

答案 0 :(得分:2)

首先,您的代码有很多问题。如果需要返回列表,则应使用get_object方法进行过滤。它只能返回一个实例,因此可以在get_queryset方法中这样做。其次,列表方法中有get_object(),这是错误的。第三,在list方法中分配序列化器类没有任何意义。在该方法被调用之前就已分配。

现在回到您的问题,“列表”是一个视图集操作,您不能执行两次。相反,您可以在列表端点上添加一个extra action。 为此,只需在视图集中的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_type设置为布尔值,但为了以防万一,我将其设置为字符串。我不知道您的url是如何配置的,所以我真的不知道如何从url kwargs中检索用户名,但是这段代码应该可以帮助您解决问题