Hey everyone, I’m stuck trying to make my Django REST API user-specific. I want to access data by adding the username at the end of the URL, like /api/notes/johndoe.
Here’s what I’ve got so far:
class PersonalInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
birthday = models.DateField()
bio = models.TextField(max_length=500)
class Memo(models.Model):
content = models.TextField(max_length=1000)
owner = models.ForeignKey(PersonalInfo, on_delete=models.CASCADE)
class MemoSerializer(serializers.ModelSerializer):
class Meta:
model = Memo
fields = ['id', 'content', 'owner']
class MemoViewSet(viewsets.ModelViewSet):
serializer_class = MemoSerializer
queryset = Memo.objects.all()
def get_queryset(self):
return self.request.owner.Memo.all()
I’ve set up the models, serializer, and view, but I can’t figure out how to make it work with usernames in the URL. Any ideas on what I’m missing or doing wrong? Thanks!
yo, i’ve been there too. try this:
in ur views.py, add:
from django.shortcuts import get_object_or_404
class MemoViewSet(viewsets.ModelViewSet):
def get_queryset(self):
username = self.kwargs.get('username')
user = get_object_or_404(User, username=username)
return Memo.objects.filter(owner__user=user)
then in urls.py:
path('api/notes/<str:username>/', MemoViewSet.as_view({'get': 'list'})),
shud work now. good luck!
I’ve dealt with this exact problem in a recent project. Here’s what I found works well:
Instead of modifying the ViewSet, I created a custom URL router. This approach gives you more flexibility and keeps your ViewSet clean.
First, define a custom router:
class UserRouter(SimpleRouter):
def get_lookup_regex(self, viewset, lookup_prefix=''):
return r'(?P<username>[^/.]+)'
Then, use it in your urls.py:
router = UserRouter()
router.register(r'api/notes', MemoViewSet)
urlpatterns = router.urls
In your MemoViewSet, override get_queryset:
def get_queryset(self):
username = self.kwargs.get('username')
return Memo.objects.filter(owner__user__username=username)
This setup allows for URLs like /api/notes/johndoe/ without cluttering your ViewSet. Just ensure you’re handling permissions correctly to prevent unauthorized access.
I’ve encountered a similar issue before, and here’s what worked for me:
Modify your MemoViewSet to include a lookup_field and lookup_url_kwarg:
class MemoViewSet(viewsets.ModelViewSet):
serializer_class = MemoSerializer
lookup_field = 'owner__user__username'
lookup_url_kwarg = 'username'
def get_queryset(self):
username = self.kwargs.get('username')
return Memo.objects.filter(owner__user__username=username)
Then, update your URLs:
urlpatterns = [
path('api/notes/<str:username>/', MemoViewSet.as_view({'get': 'list', 'post': 'create'})),
path('api/notes/<str:username>/<int:pk>/', MemoViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
This approach should allow you to access memos via URLs like /api/notes/johndoe/. Remember to handle permissions appropriately to ensure users can only access their own data.