我正在使用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')
我想要的是遵循端点
/contact-phone/{contact_id}/
列出特定联系人的电话号码 /contact-phone/{contact_id}/
为特定联系人添加电话号码 /contact-phone/{contact_phone_number_id}/
更新特定电话号码 /contact-phone/{contact_phone_number_id}/
删除特定的电话号码 PUT
和Delete
可以作为ModelViewSet
的默认操作实现,但如何使get_queryset
接受contact_id
作为必需参数?< /强>
编辑2
我关注了文档Binding ViewSets to URLs explicitly
更新 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'
答案 0 :(得分:1)
您可以使用@action
装饰器向视图集添加额外的操作:
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
网址,请使用明确的网址绑定:
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),
]