Django,DRF, get another app's view name for a reverse - python

I'm trying to create a link for another app in my serializer using the solution provided here:
https://stackoverflow.com/a/45850334/12177026
I'm trying to match the view's name but every way I try I get this error:
Reverse for 'KnownLocationView' not found. 'KnownLocationView' is not a valid view function or pattern name.
serializers:
class MissionSerializer(HyperlinkedModelSerializer):
gdt = ChoiceField(choices=lazy(get_locations, tuple)())
location = SerializerMethodField(label='Open Location')
def get_location(self, obj):
request = self.context.get('request')
return request.build_absolute_uri(reverse('KnownLocationView', kwargs={'Name': obj.gdt}))
class Meta:
model = Mission
fields = ('MissionName', 'UavLatitude', 'UavLongitude', 'UavElevation', 'Area',
'gdt', 'location')
KnownLoction/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import KnownLocationView
app_name = 'KnownLocation'
router = DefaultRouter()
router.register(r'knownlocations', KnownLocationView)
urlpatterns = [
path('', include(router.urls)),
]
I tried replacing view_name with either of the following:
'knownlocations'
'KnownLocation:knownlocations'
'KnownLocation:KnownLocationView'
But get the same error
even tried to reorder the installed apps.
api/urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('', include('landingpage.urls')), # API Landing Page
path('', include('ThreeLocations.urls')), # Triangulation between two Known GDTs and uav location.
path('', include('SecondGDT.urls')), # Options For Second GDT Positioning.
path('', include('KnownLocation.urls', namespace='knownlocations')),
# Add Known Location To the map.
] + staticfiles_urlpatterns()
KnownLocation/views.py
from rest_framework.renderers import AdminRenderer
from rest_framework.viewsets import ModelViewSet
from .models import KnownLocation
from .serializers import KnownLocationSerializer
class KnownLocationView(ModelViewSet):
"""
List of Known Locations In which we can place one of our ground positions.
press create to add a new location.
"""
serializer_class = KnownLocationSerializer
queryset = KnownLocation.objects.all()
def get_serializer_context(self):
data = KnownLocationSerializer(self.queryset, many=True, context={'request': self.request})
return data
renderer_classes = [AdminRenderer]

I think you should try to change how you are calling the reverse.
You can find reference to it below
Note: If using namespacing with hyperlinked serializers you'll also need to ensure that any view_name parameters on the serializers correctly reflect the namespace. In the examples above you'd need to include a parameter such as view_name='app_name:user-detail' for serializer fields hyperlinked to the user detail view.
The automatic view_name generation uses a pattern like %(model_name)-detail. Unless your models names actually clash you may be better off not namespacing your Django REST Framework views when using hyperlinked serializers.
Try using this
reverse('KnownLocationView:mission-detail, kwargs={'Name': obj.gdt})
Or
reverse('mission-detail, kwargs={'Name': obj.gdt})

Related

DRF: How to use urls with UUID

So, I would like top stop ursing urlpatterns and just use router. But instead of using ID of an object I'm using UUID instead and I'm using it with urlpatterns and dont't find some way to use it with routers.
this is my current model:
class Board(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=200, blank=False, null=False)
this is my core app urls.py:
...
router = DefaultRouter()
router.register(r'boards', BoardViewSet)
router.register(r'y', yViewSet)
router.register(r'z', zViewSet, basename='z')
urlpatterns = [
path('', include(router.urls)),
path('board-list/<uuid:pk>/', BoardViewSet.as_view({'get': 'list'}), name='boards'),
]
and this is the project urls.py:
from django.contrib import admin
from django.urls import path, include
from core.urls import router as api_router
routes = []
routes.extend(api_router.urls)
urlpatterns = [
path('api/', include((routes, 'board_microservice'), namespace='v1')),
path('admin/', admin.site.urls),
]
the application usage is ok, but I have some troubles with test.
i.e:
this works well:
url = reverse('v1:board-list')
response = api_client().get(
url
)
and it isn't working:
board = baker.make(Board)
url = reverse('v1:board-list', kwargs={"pk": board.id})
response = api_client().get(url)
I receive
django.urls.exceptions.NoReverseMatch: Reverse for 'board-list' with keyword arguments
and I think I can replace urlpatterns by router to solve it and turns it more simple
There is any way to do it with router?
You haven't shared your view, but it seems you are using a ModelViewSet and you seem to be looking for the retrieve endpoint rather than list (judging from using a pk). If so then you want to use -detail instead of -list:
url = reverse('v1:board-detail', kwargs={"pk": board.id})
Board_list is not what you want to call... Try board_get instead.
Board list takes no argument. But get does.. To get a particular board.

Having trouble in routing ( giving urls or path) in Django Rest Framework

This is my main project urls . Now I have an app which is routed by path('', include('mysite.urls')),. Now I have a folder named crmAPi for creating apis. This api folder is not an app though, just a folder. I route the urls by using path('api', include("mysite.crmapi.urls")),.
urlpatterns = [
path('', include('mysite.urls')),
path('admin/', admin.site.urls),
path('api', include("mysite.crmapi.urls")),
]
Now, this is my crmApi urls. The problem is I can access to first path, i can see airilnes list. No, matter what i do, i cannot acces flightdetails. What is the problem with the route?? help pleaseee?? even i create a different listview, again I cannot the route, only the arilines one, I can access.
urlpatterns = [
path('', views.AirlinesListAPIView.as_view(), name='api'),
path('api/flightdetails', views.FlightDetailsListAPIView.as_view(), name='flightdetails'),
]
This is my view.
class AirlinesListAPIView(ListAPIView):
# permission_classes = [AllowAny]
serializer_class = AirlinesListSerailizer
queryset = Airlines.objects.all()
permission_classes = (IsAdminUser,)
class FlightDetailsListAPIView(ListAPIView):
# permission_classes = [AllowAny]
serializer_class = FlightDetailsListSerailizer
queryset = FlightDetails.objects.all()
permission_classes = (IsAdminUser,)
Well, you included the api.urls under api/ path. And inside api.urls you also have api/flightdetails, which contains api.
My assumption is that you're trying to access http://127.0.0.1/api/flightdetails, but it doesn't actually exist, because FlightDetailsListAPIView is accessible under http://127.0.0.1/api/api/flightdetails.
If you want access it via http://127.0.0.1/api/flightdetails, you should rename the path to:
path('flightdetails/', views.FlightDetailsListAPIView.as_view(), name='flightdetails'),

Stuck creating a Django REST Framework ViewSet

I am stuck trying to work out how to create a Django REST Framework ViewSet.
The API calls I have inherited look like this:
/api/v1/user/<user_id>/like_count
/api/v1/user/<user_id>/friends/
/api/v1/user/login
/api/v1/user/logout/
In my base urls.py I have the following:
urlpatterns = patterns('',
url(r'^api/v1/', include('api.urls')),
url(r'^$', TemplateView.as_view(template_name='base.html'), name='home'),
url(r'^docs/', include('rest_framework_swagger.urls'))
)
I have an app called api. In the api urls.py I have:
from django.conf.urls import url, include
from rest_framework import routers
from api import views
router = routers.DefaultRouter()
router.register(r'user', views.UserViewSet)
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
In my api/views.py file I want to create a UserViewSet class that handles all the possible variants of the url calls.
First I can't work out if I should use:
class UserViewSet(viewsets.ModelViewSet):
or...
class UserViewSet(APIView):
If I understand it correctly I can cater for the
/api/v1/user/login
/api/v1/user/logout
calls using something like:
class UserViewSet(viewsets.APIView):
def login(self, request, format=None):
...
def logout(self,request, format=None):
But I can't work out how to cater for the other variants that have the <user-id> in the url.
Is there a recommended way to do this?
Some API calls have a trailing '/' and some don't. It is what I have been given (to fit in with an existing mobile app).
EDIT: By the way, I have done the DRF tutorial twice now and still can't see how to do this.
EDIT2: I am really struggling to understand the DRF documentation for this. Can anyone provide some example code that deals with my use case?
Using a ViewSet or Views will depend on what other actions you need for your user resource apart from those you have in your urls. ModelViewSet is built from mixins for listing, updating etc. You can combine those to achieve what you want or you can just go with a combination of views.
Of course you can combine a viewset with views if you have to.
For the /api/v1/user/<user_id>/friends/ endpoint you can look at DRF docs or at DRF Nested Routers.
The like_count can be implemented with a view that returns just that single value.
Auth is a different topic entirely --- you can look at this.
viewsets.py
class UserViewset(viewsets.ModelViewSet):
lookup_field = 'id'
serializer_class = UserSerializer
queryset = User.objects.all()
urls.py
from .viewsets import UserViewSet
user_list = UserViewSet.as_view({'get':'list'})
user_detail = UserViewSet.as_view({'get':'retrieve'})
urlpatterns= [
url(r'^user/(?P<id>\d+)/(?P<friends>[-\w\d]+)/$', user_detail, name='user-detail')
]
In the serializers.py adde the ParameterisedHyperlinkedIdentityField as a serializer.
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = ParameterisedHyperlinkedIdentityField(view_name='user-detail', lookup_fields=(('id', 'id'), ('friends', 'friends')), read_only=True)
class Meta:
model = User

Listview Class based view is not working properly

I am using class based views in my app but I am stuck at one point. I am using ListView and created two classes which are sub-classes of ListView.
views.py
class blog_home(ListView):
paginate_by = 3
model= Blog
context_object_name = 'blog_title'
template_name = 'blog.html'
class blog_search(ListView):
paginate_by = 4
context_object_name = 'blog_search'
template = 'blog_search.html'
def get_queryset(self):
self.search_result = Blog.objects.filter(title__contains = 'Static')
return self.search_result
urls.py
urlpatterns = [
url(r'^$', index, name='index'),
url(r'^grappelli/', include('grappelli.urls')),
url(r'^blog/', blog_home.as_view(), name='blog_home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^blog/search/',blog_search.as_view(),name='blog_search'),
]
In my above code in blog_Search(), get_queryset() method is not getting called. I mean it's not working. If I use same same method in blog_home it does work.
blog_search not filtering. I added print statement also but not get called.
Can I create two classes with ListView in same file? Is this the problem?
You need to terminate your blog/ URL entry. Without termination, it matches all URLs beginning with "blog/", including "blog/search", so no requests ever make it to the blog_search view.
url(r'^blog/$', blog_home.as_view(), name='blog_home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^blog/search/$',blog_search.as_view(),name='blog_search'),

Struggling to get django_comments to work with Django REST Framework

I'm using Django REST Framework for the first time on a project and I'm struggling with one particular part. The project is an issue tracker-type applicaton and it uses django_comments to allow for comments on issues. I'm now building an API on top of it to allow for creating a mobile app.
I've created the following serializers:
from django.contrib.auth.models import User
from todolist.models import Project, Issue
from rest_framework import serializers
from django_comments.models import Comment
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('id', 'email', 'first_name', 'last_name')
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Project
fields = ('name', 'description', 'owner')
class CommentSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Comment
class IssueSerializer(serializers.HyperlinkedModelSerializer):
comments = CommentSerializer(many=True)
class Meta:
model = Issue
And here's my project-wide urls.py, where I define the routes:
from django.conf.urls import patterns, include, url
from todolist.views import HomeTemplateView, UserViewSet, ProjectViewSet, IssueViewSet, CommentViewSet
from rest_framework import routers
from rest_framework.authtoken.views import obtain_auth_token
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'projects', ProjectViewSet)
router.register(r'issues', IssueViewSet)
router.register(r'comments', CommentViewSet)
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'projectile.views.home', name='home'),
# url(r'^projectile/', include('projectile.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
# Comments
(r'^comments/', include('django_comments.urls')),
# Login
url(r'^accounts/login/$', 'django.contrib.auth.views.login'),
# Logout
url(r'^accounts/logout/$', 'django.contrib.auth.views.logout_then_login', {'login_url': '/accounts/login/'}),
# To-do list
url(r'^projects/', include('todolist.urls')),
# Home page
url(r'^$', HomeTemplateView.as_view(
template_name="todolist/home.html",
)),
# Router URLs
url(r'^api/', include(router.urls)),
# REST framework auth URLs
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api-token-auth/', obtain_auth_token),
# API docs
url(r'^docs/', include('rest_framework_swagger.urls'))
)
I'm seeing the following error when I run a test which tries to get all the comments:
ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "contenttype-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
Also, when I fetch an issue, it doesn't include the comments.
Now, this error appears to me to be that when fetching a comment, it's unable to match up the comment to its parent. I've experienced similar problems when using Tastypie in the past, and I'm unsure how to resolve it with DRF.
In your Comment serializer, specify comment instances fields explicitly and exclude field contenttype.
class CommentSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Comment
fields = ('field_1','field_2','field_3') #here goes your comment fields and dont include contenttype field
The problem is that DRF will try to apply hyperlinks to represent all relationships, and for contenttype field you don't have a view or a serializer and you dont need it either.

Categories