我正在使用 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")
如果有人能指出我的错误并给我一些指导,因为我对此很陌生,谢谢!
看来问题与
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
。