我是Django REST Framework
的新手。我想我已经搞砸了,因为有时感觉DRF很容易理解,但后来它搞砸了。
我有一个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)
date_of_birth = models.DateField(blank=True, null=True)
class ContactEmail(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
email = models.EmailField()
class ContactPhoneNumber(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
phone = models.CharField(max_length=100)
每个联系人都与一些经过身份验证的用户相关。
联系人/ serializers.py
class ContactPhoneNumberSerializer(serializers.ModelSerializer):
class Meta:
model = ContactPhoneNumber
fields = ('id', 'phone')
class ContactEmailSerializer(serializers.ModelSerializer):
class Meta:
model = ContactEmail
fields = ('id', 'email')
class ContactSerializer(serializers.HyperlinkedModelSerializer):
phone_numbers = ContactPhoneNumberSerializer(source='contactphonenumber_set', many=True)
emails = ContactEmailSerializer(source='contactemail_set', many=True)
class Meta:
model = Contact
fields = ('url', 'id', 'first_name', 'last_name', 'date_of_birth',
'phone_numbers', 'emails')
和 contacts / views.py
class ContactViewSet(viewsets.ModelViewSet):
queryset = Contact.objects.all()
serializer_class = ContactSerializer
permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)
def perform_create(self, serializer):
serializer.save(user_id=self.request.user)
到目前为止,我遵循Django REST Framework
的文档,但它显示了所有联系人,而不是仅显示用户的联系人。
为此,我添加了get_queryset()
class ContactViewSet(viewsets.ModelViewSet):
# queryset = Contact.objects.all()
...
def get_queryset(self):
return Contact.objects.filter(user=self.request.user)
...
但它开始给出错误
assert queryset is not None, '`base_name` argument not specified, and could ' \
AssertionError: `base_name` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.queryset` attribute.
在做了一些研究后,我发现在路由器
中添加了第三个参数应用/ urls.py
router = routers.DefaultRouter()
router.register(r'contacts', ContactViewSet, 'contacts') # added 'contacts' here
urlpatterns = [
path('api/', include(router.urls))
]
但不是解决问题,而是产生了新的错误
django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked
relationship using view name "contact-detail".
You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
在做了一些研究之后,找到了在url
中定义searializers.py
的解决方案。所以,我更新了contacts/serializers.py
class ContactSerializer(serializers.HyperlinkedModelSerializer):
phone_numbers = ...
emails = ...
url = serializers.HyperlinkedRelatedField(
view_name='contacts:detail'
)
class Meta:
model = Contact
fields = ('url', 'id', 'first_name', 'last_name', 'date_of_birth',
'phone_numbers', 'emails')
但现在,它已经开始发出新的错误
'Relational field must provide a `queryset` argument, '
AssertionError: Relational field must provide a `queryset` argument, override `get_queryset`, or set read_only=`True`.
由于我的应用程序是基于用户的,并且每个经过身份验证的用户都可以查看/编辑/删除自己的数据,因此只有基于request.user
过滤对象的简单方法。 < / p>
此外,有没有办法让这个问题得到解决,因为我在这里混淆了哪个关系字段?
答案 0 :(得分:0)
我没有使用ModelViewSet。 但是在常规APIView中,你可以这样做:
class SingleProject(APIView):
def get(self, request):
project_id = request.query_params.get('id')
ans = Project.objects.filter(id=project_id)
serializer = EagerGetProjectSerializer(qs, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
所以也许是这样的:
class ContactViewSet(viewsets.ModelViewSet):
queryset = Contact.objects.filter(user=self.request.user)
serializer_class = ContactSerializer
permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)
答案 1 :(得分:0)
这解决了我的问题
将read_only=True
设为url
url = serializers.HyperlinkedRelatedField(
view_name='contacts:detail',
read_only=True
)