62๐
โ
DRF adds suffixes in viewsets for different URLs โ list, detail and possibly custom URLs. You can see that in source code and in docs. So in your case the actual reverse should be something like:
reverse('api:my_list-list') # for list URL. e.g. /api/my-list/
reverse('api:my_list-detail') # for detail URL. e.g. /api/my-list/<pk>/
That is why its also probably better to use a resource name as a router base_name
. For example base_name='user'
vs base_name='users_list'
.
๐คmiki725
2๐
Update 2021.
I have added more details from from @miki725 answer.
There are some details that needs to have some considerations such as app_name
parameter that need to be placed within the myappname.urls
.
Therefore the urls.py
should look like this:
# django imports
from django.urls import path, include
# drf imports
from rest_framework import routers
from myappname.viewsets import UserViewSet
# In the example used in the question the app_name is 'api'
app_name = 'myappname' # <---- Needed when testing API URLS..
router = routers.DefaultRouter()
router.register(r'users', UserViewSet, basename='user') # <---- Here already have -list and -detail by default.
urlpatterns = [
path('', include(router.urls)),
]
tests.py
from myappname.models import User
from django.urls import reverse
from django.utils import timezone
from rest_framework import status
from rest_framework.test import APITestCase
class TestApi(APITestCase):
def setUp(self):
self.headerInfo = {'content-type': 'application/json'}
# example of query to be used on URL.
self.user = User.objects.create(
username = 'anyname',
created_at=timezone.now(),
created_by='testname',
)
self.user.save()
# payload to be used to test PUT method for example...
self.user_data = {
'username': 'othername',
'created_at': timezone.now(),
'created_by': 'othertestname'
}
# again: In the example used in the question the app_name is 'api'
# that's why reverse('api:my-list')...
self.url_user_list = reverse('myappname:user-list') # <------
self.url_user_detail = reverse('myappname:user-detail',
kwargs={'pk': self.user.pk}) # <------
"""
Test User endpont.
"""
def test_get_user(self):
"""GET method"""
response = self.client.get(self.url_user_list,
self.user_data,
format='json'
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_create_user(self):
""" test POST method for User endpoint"""
response = self.client.post(
self.url_user_list, self.user_data,
# headers=self.headerInfo,
format='json'
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
def test_update_user(self):
data = {
'username': 'someothername',
'created_at': timezone.now(),
'created_by': 'someothertestname'
}
response = self.client.put(self.url_user_detail, data, headers=self.headerInfo)
self.assertEqual(response.status_code, status.HTTP_200_OK)
๐คElias Prado
- [Django]-Django on IronPython
- [Django]-Django: Model Form "object has no attribute 'cleaned_data'"
- [Django]-'function' object has no attribute 'as_view'
Source:stackexchange.com