使用 DRF 检索视图集获取一个对象,无需 pk 或 uuid

问题描述 投票:0回答:1

我正在使用 python DRF 为商家资料页面设计一个 api。不应要求将 ID 传递到 api 中。

我正在尝试执行一次简单的获取来获取一个对象作为结果返回,并且我读到检索可用于此功能。

这是我的代码:

models.py:

# Create your models here.
class Merchant(models.Model):
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True)
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    def __str__(self):
        return self.merchantprofile.organization_name


class MerchantProfile(models.Model):
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True)
    merchant = models.OneToOneField(Merchant, on_delete=models.CASCADE)
    organization_name = models.CharField(max_length=255)
    since = models.DateTimeField(auto_now_add=True)
    mobile_number = models.CharField(max_length=20, null=True, blank=True)
    email = models.EmailField(null=True, blank=True)
    website_url = models.CharField(max_length=100, null=True, blank=True)

views.py:

class MerchantProfileViewSet(AuthenticationMixin, RetrieveModelMixin, ListModelMixin, UpdateModelMixin, GenericViewSet):
    queryset = MerchantProfile.objects.all()
    serializer_class = MerchantProfileSerializer
    lookup_field = "uuid"

    def retrieve(self, request, *args, **kwargs):
        user_id = self.request.user.id       
        instance = MerchantProfile.objects.get(merchant__user=user_id)
        serializer = MerchantProfileSerializer(instance)
        return Response(serializer.data, status=status.HTTP_200_OK)

urls.py:

merchant_router = DefaultRouter()
merchant_router.register('/profile',  MerchantProfileViewSet, basename="merchantprofile")

urlpatterns = [
   path('merchant', include(merchant_router.urls)),
]

序列化器.py

class MerchantProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = MerchantProfile
        fields = ["organization_name", 'since', 'mobile_number', 'email', 'website_url',
                  'facebook_url', 'instagram_url', 'tiktok_url', 'youtube_url', 'xhs_url']

无论我如何调整,我总是得到这个

但这就是我想要的样子(我设法通过使用列表方法得到这个,但我被告知我应该能够通过检索来实现,并且检索应该是要走的路,而不是使用列表,这是一个这种特殊情况下的解决方法)

    def list(self, request):
        user_id = self.request.user.id

        try:
            qs = MerchantProfile.objects.get(merchant__user=user_id)
            serializer = self.serializer_class(qs)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except:
            raise Http404("Merchant profile does not exist for the current user")

如果有人能指出我的错误并给我一些指导,因为我对此很陌生,谢谢!

python django-rest-framework django-urls django-rest-viewsets
1个回答
-1
投票

看来问题与

get()
函数中的
retrieve
方法有关。在
retrieve
方法中,您通常使用从
get_object()
继承的
RetrieveModelMixin
方法来根据提供的查找字段获取特定实例。

在您的情况下,您似乎想根据

MerchantProfile
检索
user_id
实例。您已在视图中设置了
lookup_field = "uuid"
,但您似乎正在尝试根据
MerchantProfile
过滤
user_id
。如果你想这样做,你需要调整你的观点。

以下是修改

retrieve
方法的方法:

from django.shortcuts import get_object_or_404

class MerchantProfileViewSet(AuthenticationMixin, RetrieveModelMixin, ListModelMixin, UpdateModelMixin, GenericViewSet):
    queryset = MerchantProfile.objects.all()
    serializer_class = MerchantProfileSerializer
    lookup_field = "uuid"

    def retrieve(self, request, *args, **kwargs):
        # Use get_object_or_404 to handle the case where the object is not found
        user_id = self.request.user.id
        instance = get_object_or_404(MerchantProfile, merchant__user=user_id)
        serializer = MerchantProfileSerializer(instance)
        return Response(serializer.data, status=status.HTTP_200_OK)

这样,如果找不到对象,

get_object_or_404
函数将引发
Http404
异常,并且您不需要额外的 try- except 块。

确保您的 URL 模式设置正确,以在调用

uuid
端点时包含
retrieve
参数。如果您以
/merchant/profile
的形式访问它,则可能需要在 URL 中提供
uuid
,如
/merchant/profile/<uuid:uuid>

此外,如果您仍然想保留

list
方法,可以使用
get_queryset
方法来提供基于用户的查询集:

def get_queryset(self):
    user_id = self.request.user.id
    return MerchantProfile.objects.filter(merchant__user=user_id)

这样,

list
retrieve
方法将使用相同的逻辑来根据用户获取查询集。

更新:

如果您想基于主键或 uuid 之外的字段获取单个实例,您可以自定义检索端点的行为。在您的例子中,您提到

MerchantProfile
User
模型是一对一的关系,并且您想要检索与当前经过身份验证的用户关联的
MerchantProfile

假设

User
模型和
MerchantProfile
模型之间有直接关系,您可以修改
retrieve
方法以根据 user_id 获取实例,而无需在 URL 中显式传递 uuid。

这是一个例子:

from rest_framework.mixins import RetrieveModelMixin
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from rest_framework import status

class MerchantProfileViewSet(AuthenticationMixin, RetrieveModelMixin, GenericViewSet):
    serializer_class = MerchantProfileSerializer
    lookup_field = "uuid"

    def retrieve(self, request, *args, **kwargs):
        # Fetch the currently authenticated user
        user = request.user

        # Retrieve the associated MerchantProfile using the one-to-one relationship
        instance = user.merchantprofile

        serializer = MerchantProfileSerializer(instance)
        return Response(serializer.data, status=status.HTTP_200_OK)

这假设

User
MerchantProfile
之间存在一对一关系,并且
User
模型中一对一字段的相关名称设置为
merchantprofile
。根据您的实际模型调整字段名称和关系。

通过这种方法,检索端点可获取与当前经过身份验证的用户关联的

MerchantProfile
实例,而无需在 URL 中提供显式 uuid。从请求中获取user_id,通过一对一关系获取关联的
MerchantProfile

© www.soinside.com 2019 - 2024. All rights reserved.