在Django REST框架中为get

编程入门 行业动态 更新时间:2024-10-28 20:31:17
在Django REST框架中为get_queryset请求添加参数(add parameter to get_queryset request in Django REST Framework)

我正在使用Django 2.0和Django REST Framework 。

我在联系人应用程序中有两个模型

联系人/ models.py

class Contact(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100, blank=True, null=True, default='') class ContactPhoneNumber(models.Model): contact = models.ForeignKey(Contact, on_delete=models.CASCADE) phone = models.CharField(max_length=100) primary = models.BooleanField(default=False) def __str__(self): return self.phone

联系人/ serializers.py

class ContactPhoneNumberSerializer(serializers.ModelSerializer): class Meta: model = ContactPhoneNumber fields = ('id', 'phone', 'primary', 'created', 'modified')

contacts / views.py

class ContactPhoneNumberViewSet(viewsets.ModelViewSet): serializer_class = ContactPhoneNumberSerializer def get_queryset(self): return ContactPhoneNumber.objects.filter( contact__user=self.request.user )

urls.py

router.register(r'contact-phone', ContactPhoneNumberViewSet, 'contact_phone_numbers')

我想要的是遵循端点

GET: /contact-phone/{contact_id}/ 列出特定联系人的电话号码 POST: /contact-phone/{contact_id}/ 将电话号码添加到特定联系人 PUT: /contact-phone/{contact_phone_number_id}/ 更新特定的电话号码 删除: /contact-phone/{contact_phone_number_id}/ 删除特定的电话号码

PUT和Delete可以作为get_queryset默认动作来实现,但是如何让get_queryset接受contact_id作为所需参数?

编辑2

我明确遵循了文档Binding ViewSet到URL

更新app / urls.py

router = routers.DefaultRouter() router.register(r'contacts', ContactViewSet, 'contacts') contact_phone_number_view_set = ContactPhoneNumberViewSet.as_view({ 'get': 'list/<contact_pk>/', 'post': 'create/<contact_pk>/', 'put': 'update', 'delete': 'destroy' }) router.register(r'contact-phone-number', contact_phone_number_view_set, 'contact_phone_numbers') urlpatterns = [ path('api/', include(router.urls)), url(r'^admin/', admin.site.urls), ]

但它给错误

AttributeError: 'function' object has no attribute 'get_extra_actions'

I'm using Django 2.0 and Django REST Framework.

I have two models in contacts app

contacts/models.py

class Contact(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100, blank=True, null=True, default='') class ContactPhoneNumber(models.Model): contact = models.ForeignKey(Contact, on_delete=models.CASCADE) phone = models.CharField(max_length=100) primary = models.BooleanField(default=False) def __str__(self): return self.phone

contacts/serializers.py

class ContactPhoneNumberSerializer(serializers.ModelSerializer): class Meta: model = ContactPhoneNumber fields = ('id', 'phone', 'primary', 'created', 'modified')

and contacts/views.py

class ContactPhoneNumberViewSet(viewsets.ModelViewSet): serializer_class = ContactPhoneNumberSerializer def get_queryset(self): return ContactPhoneNumber.objects.filter( contact__user=self.request.user )

urls.py

router.register(r'contact-phone', ContactPhoneNumberViewSet, 'contact_phone_numbers')

What I want is following endpoints

GET: /contact-phone/{contact_id}/ list phones numbers of particular contact POST:/contact-phone/{contact_id}/ add phone numbers to particular contact PUT: /contact-phone/{contact_phone_number_id}/ update particular phone number DELETE: /contact-phone/{contact_phone_number_id}/ delete particular phone number

PUT and Delete can be achieved as default action of ModelViewSet but how to make get_queryset to accept contact_id as required parameter?

Edit 2

I followed doc Binding ViewSets to URLs explicitly

update app/urls.py

router = routers.DefaultRouter() router.register(r'contacts', ContactViewSet, 'contacts') contact_phone_number_view_set = ContactPhoneNumberViewSet.as_view({ 'get': 'list/<contact_pk>/', 'post': 'create/<contact_pk>/', 'put': 'update', 'delete': 'destroy' }) router.register(r'contact-phone-number', contact_phone_number_view_set, 'contact_phone_numbers') urlpatterns = [ path('api/', include(router.urls)), url(r'^admin/', admin.site.urls), ]

But it is giving error

AttributeError: 'function' object has no attribute 'get_extra_actions'

最满意答案

你可以使用@action decorator为视图添加额外的动作:

class ContactPhoneNumberViewSet(viewsets.ModelViewSet): serializer_class = ContactPhoneNumberSerializer def get_queryset(self): return ContactPhoneNumber.objects.filter( contact__user=self.request.user ) @action(methods=['post'], detail=False) def add_to_contact(self, request, contact_id=None): contact = Contact.objects.get(id=contact_id) serializer = ContactPhoneNumberSerializer(data=request.data) if serializer.is_valid(): serializer.save(contact=contact) return Response(serializer.data) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @action(methods=['get'], detail=False) def set_password(self, request, contact_id=None): contact = Contact.objects.get(id=contact_id) serializer = PasswordSerializer(contact.contactphonenumber_set.all(), many=True) return Response(serializer.data)

UPD

由于您不需要额外的操作,因此可以覆盖retrieve并create默认方法:

class ContactPhoneNumberViewSet(viewsets.ModelViewSet): serializer_class = ContactPhoneNumberSerializer def get_queryset(self): return ContactPhoneNumber.objects.filter( contact__user=self.request.user ) def create(self, request, pk=None): contact = Contact.objects.get(id=contact_id) serializer = ContactPhoneNumberSerializer(data=request.data) if serializer.is_valid(): serializer.save(contact=contact) return Response(serializer.data) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def retrieve(self, request, pk=None): contact = Contact.objects.get(pk=pk) serializer = PasswordSerializer(contact.contactphonenumber_set.all(), many=True) return Response(serializer.data)

要更改标准的create url使用明确的url绑定:

contact_list = ContactPhoneNumberViewSet.as_view({ 'get': 'list', 'post': 'create', 'put': 'update', 'delete': 'destroy' }) urlpatterns = [ path('api//contact-phone/<int:pk>/', contact_list, name='contact-list'), url(r'^admin/', admin.site.urls), ]

You can add extra actions to the viewset using @action decorator:

class ContactPhoneNumberViewSet(viewsets.ModelViewSet): serializer_class = ContactPhoneNumberSerializer def get_queryset(self): return ContactPhoneNumber.objects.filter( contact__user=self.request.user ) @action(methods=['post'], detail=False) def add_to_contact(self, request, contact_id=None): contact = Contact.objects.get(id=contact_id) serializer = ContactPhoneNumberSerializer(data=request.data) if serializer.is_valid(): serializer.save(contact=contact) return Response(serializer.data) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @action(methods=['get'], detail=False) def set_password(self, request, contact_id=None): contact = Contact.objects.get(id=contact_id) serializer = PasswordSerializer(contact.contactphonenumber_set.all(), many=True) return Response(serializer.data)

UPD

Since you don't need additional actions, you can override retrieve and create defaults methods:

class ContactPhoneNumberViewSet(viewsets.ModelViewSet): serializer_class = ContactPhoneNumberSerializer def get_queryset(self): return ContactPhoneNumber.objects.filter( contact__user=self.request.user ) def create(self, request, pk=None): contact = Contact.objects.get(id=contact_id) serializer = ContactPhoneNumberSerializer(data=request.data) if serializer.is_valid(): serializer.save(contact=contact) return Response(serializer.data) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def retrieve(self, request, pk=None): contact = Contact.objects.get(pk=pk) serializer = PasswordSerializer(contact.contactphonenumber_set.all(), many=True) return Response(serializer.data)

To change standard create url use explicitly url binding:

contact_list = ContactPhoneNumberViewSet.as_view({ 'get': 'list', 'post': 'create', 'put': 'update', 'delete': 'destroy' }) urlpatterns = [ path('api//contact-phone/<int:pk>/', contact_list, name='contact-list'), url(r'^admin/', admin.site.urls), ]

更多推荐

本文发布于:2023-08-07 20:19:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1465814.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:中为   框架   Django   REST

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!