Django REST Framework仅显示当前认证用户联系人的问题求助
Hey there! Let's work through your DRF contacts app issues step by step—this is a super common scenario for beginners, so you're not alone here.
1. Simple Way to Filter Data by request.user
The most straightforward approach is to override the get_queryset method in your ViewSet, but you need to do it correctly to avoid those annoying errors. Here are two reliable ways:
Option 1: Keep the queryset Property (Easiest)
Just leave the base queryset intact, then filter it in get_queryset—DRF will automatically infer the base_name from the model, so you don't have to mess with route settings:
from rest_framework import viewsets from .models import Contact from .serializers import ContactSerializer from rest_framework.permissions import IsAuthenticated class ContactViewSet(viewsets.ModelViewSet): # Keep this line so DRF can auto-detect the base_name queryset = Contact.objects.all() serializer_class = ContactSerializer # Ensure only logged-in users can access their contacts permission_classes = [IsAuthenticated] def get_queryset(self): # Filter to only return contacts belonging to the current user return self.queryset.filter(user=self.request.user)
Option 2: Omit queryset but Specify basename in Routes
If you don't want to keep the base queryset, you need to explicitly tell DRF what base_name to use when registering your route:
# In your views.py class ContactViewSet(viewsets.ModelViewSet): serializer_class = ContactSerializer permission_classes = [IsAuthenticated] def get_queryset(self): return Contact.objects.filter(user=self.request.user)
Then in your urls.py:
from django.urls import path, include from rest_framework.routers import DefaultRouter from .views import ContactViewSet router = DefaultRouter() # Add the third argument `basename='contact'` here router.register(r'contacts', ContactViewSet, basename='contact') urlpatterns = [ path('', include(router.urls)), ]
2. Fixing the Errors You Encountered
Let's tackle each error one by one:
AssertionError: "Need to specify base_name"
This happens because when you remove the queryset property, DRF can't automatically figure out what to name your route endpoints. The fix is exactly what's above—either keep the queryset or add basename to your router registration.
URL Resolution Error: "Could not resolve view name 'contact-detail'"
This usually means your base_name doesn't match what your serializer expects. If you set basename='contact' in the router, the detail view name becomes contact-detail—make sure your serializer's URL field uses this exact name. For example, if you're using HyperlinkedIdentityField:
# In your serializers.py from rest_framework import serializers from .models import Contact class ContactSerializer(serializers.ModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='contact-detail', # Must match the base_name + "-detail" lookup_field='pk' ) # Mark user as read-only since we'll auto-set it to the current user user = serializers.PrimaryKeyRelatedField(read_only=True) class Meta: model = Contact fields = ['url', 'id', 'name', 'email', 'phone', 'user'] # Auto-assign the current user when creating a contact def create(self, validated_data): validated_data['user'] = self.context['request'].user return super().create(validated_data)
Error: "Related field must provide a queryset..."
This pops up if you're using a related field (like user) without setting it to read-only or providing a queryset. Since we don't want users to manually set the user field (we'll auto-assign the logged-in user), just mark user as read_only=True in the serializer, as shown above. Alternatively, if you needed to let users select a user (not your case here), you'd add queryset=User.objects.all() to the field.
Final Checks
- Make sure your
Contactmodel has auserforeign key to Django'sUsermodel:from django.db import models from django.contrib.auth.models import User class Contact(models.Model): name = models.CharField(max_length=100) email = models.EmailField() phone = models.CharField(max_length=20) user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='contacts') - Don't forget to enable authentication in your
settings.py(DRF uses session auth by default, but you can add token auth if needed):REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ] }
That should cover all your issues—you'll have a contacts app where each user only sees and manages their own contacts!
内容的提问来源于stack exchange,提问作者Anuj TBE

