Api root on django rest framework - python

I am newbie on DRF so I wonder if there a "elegant" way to add more endpoints to API Root. I have an endpoint to manage my users and another to manage their posts, but on http://localhost:8000/api/ only profiles appears. I search for some solutions that implies change the URL but I don't want that. For example my current endpoint to get all posts is localhost:8000/api/posts that looks fine. I don't want something like api/posts/posts or similar. Is there any alternative?
{
"profiles": "http://localhost:8000/api/profiles/"
}
main urls.py
urlpatterns = [
path('docs/', schema_view.with_ui('swagger',
cache_timeout=0), name='schema-swagger-ui'),
path('admin/', admin.site.urls),
path('api/', include('profiles.urls')),
path('api/', include('posts.urls')),
path('api/', include('comments.urls')),
path('api/', include('private_messages.urls')),
]
userprofile urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from rest_framework_simplejwt import views as jwt_views
from .views import UserProfileViewSet
router = DefaultRouter()
router.register('profiles', UserProfileViewSet)
urlpatterns = [
path('', include(router.urls)),
path('auth/login', jwt_views.TokenObtainPairView.as_view()),
path('auth/refresh', jwt_views.TokenRefreshView.as_view()),
]
posts urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet, PostByAuthorViewSet
router = DefaultRouter()
router.register('posts', PostViewSet)
urlpatterns = [
path('posts-by-author/<author_id>', PostByAuthorViewSet.as_view()),
path('', include(router.urls))
]

but on http://localhost:8000/api/ only profiles appears
This is the expected behavior. Django is returning the first matching path from your URL configuration file, which is the profiles module in your case. Your duplicate api/ paths are ignored.
If you really want everything to be in /api, you'd have to define all your URLs in the base urls.py file. However, I would highly recommend you keep your current structure and add the module name to your endpoints:
urlpatterns = [
path('docs/', schema_view.with_ui('swagger',
cache_timeout=0), name='schema-swagger-ui'),
path('admin/', admin.site.urls),
path('api/profiles/', include('profiles.urls')),
path('api/posts/', include('posts.urls')),
path('api/comments/', include('comments.urls')),
path('api/private_messages/', include('private_messages.urls')),
]
Otherwise your urls.py file can get messy very quickly as your project grows.
If a route like localhost:8000/api/posts/posts is bothering you, you should modify the URL configuration in your posts app. Something like this would probably work better for you:
from django.urls import path
from .views import PostViewSet, PostByAuthorViewSet
urlpatterns = [
path('by-author/<author_id>', PostByAuthorViewSet.as_view()),
path('', PostViewSet.as_view())
]
This way you'd have the routes localhost:8000/api/posts/and localhost:8000/api/posts/by-author/1. As a side note, you should probably look into filters, since posts-by-authors sounds like a viewset that can easily be included in your PostViewSet with a query parameter.

Related

How to route specific urls in a django app?

I would like to know if there is a way to include only specific url endpoints in my Django urls.py.
Lets say i have a app called auth with this auth/urls.py
urlpatterns = [
url(r'^password/reset/$', PasswordResetView.as_view(),
name='rest_password_reset'),
url(r'^password/reset/confirm/$', PasswordResetConfirmView.as_view(),
name='rest_password_reset_confirm'),
url(r'^login/$', LoginView.as_view(), name='rest_login'),
url(r'^logout/$', LogoutView.as_view(), name='rest_logout'),
url(r'^user/$', UserDetailsView.as_view(), name='rest_user_details'),
url(r'^password/change/$', PasswordChangeView.as_view(),
name='rest_password_change'),
]
Now I have a urls.py like that:
urlpatterns = [
path('/', include('dj_rest_auth.urls'))
]
this includes all endpoints from auth/urls.py.
Is there a way to select (in urls.py) which URL to include? Lets say I only want login and logout to be included on my urls.py.
urlpatterns = [
path('/', include('dj_rest_auth.urls.rest_login')),
path('/', include('dj_rest_auth.urls.rest_logout'))
]
Something like that, how can I make it work?
I did this long before.
# inside view.py just create your own custom view
# rest and rest_auth import
from rest_auth.views import LoginView, LogoutView
class CustomLogoutView(LogoutView):
# yes u can keep it blank.
# over-riding just to distinguish from library views.
pass
Then inside any app's urls.py import required views and and pass then into path.
this way only required url will be exposed.
from .views import CustomLoginView
urlpatterns = [
path('login/', CustomLoginView.as_view(), name='login'),
]
Also you can directly import that views (not urls) which are included in library. and then create urls (path) from them.

Routing with Django and React

I'm very new to working with Django and I've been relying on some tutorials to link this one to React, but the problem is that initially (when I open 127.0.0.1:8000) React loads the routes perfectly, then when I reload the page Django tries to interpret the path from urls.py and obviously can't find it.
The error is:
Page not found (404) Using the URLconf defined in memberstack.urls, Django tried these URL patterns, in this order:
admin/
api/token-auth/
core/
I hope you can help me, thanks in advance
my_project/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework_jwt.views import obtain_jwt_token
from frontend.views import index
urlpatterns = [
path('', include('frontend.urls')),
path('admin/', admin.site.urls),
path('api/token-auth/', obtain_jwt_token),
path('core/', include('core.urls')),
]
frontend/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
]
frontend/views.py
from django.shortcuts import render
def index(request):
return render(request, 'frontend/index.html')
For this, you'll have to use a catch-all in order for React to handle all the routing instead of django there.
from django.urls import path, re_path
from . import views
urlpatterns = [
path('', include('frontend.urls')),
path('admin/', admin.site.urls),
path('api/token-auth/', obtain_jwt_token),
path('core/', include('core.urls')),
re_path(r'^(?:.*)/?$', include('frontend.urls')),
]
Or
urlpatterns = [
path('', views.index),
re_path(r'^(?:.*)/?$', views.index)
]
I think the better practice would be to implement Django-Rest-Framework and build them separately.

Django Url Pattern Not Being Found

I followed a tutorial to allow users to register an account but the url path does not seem to be found. It allows me to access 127.0.0.1:8000/accounts/signup but not 127.0.0.1:8000/signup when I have set the name for it.
I tried changing the urlpatterns from a path to a url method but that didn't solve the problem.
my file structure is as follows:
App:
accounts:
urls.py
views.py
...
Server:
settings.py
urls.py
...
templates:
registration:
login.html
base.html
home.html
signup.html
manage.py
In my Server\urls.py I have
from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import TemplateView
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accounts.urls')),
path('accounts/', include('django.contrib.auth.urls')),
path('', TemplateView.as_view(template_name='home.html'), name='home'),
]
In my accounts\urls.py I have
from django.urls import path
from . import views
urlpatterns = [
path('signup/', views.SignUp.as_view(), name='signup'),
]
The error I get is
Using the URLconf defined in Server.urls, Django tried these URL patterns, in this order:
admin/
accounts/
accounts/
[name='home']
The current path, signup, didn't match any of these.
I'm not too sure what is going on since I'm still sort of new to Django and busy learning as I go along.
path('accounts/', include('accounts.urls')),
means that all urls from accounts.urls are supposed to be prefixed with accounts/.
If that's not what you want - edit this to
path('/', include('accounts.urls')),
and accounts.urls will be treated as top-level urls.

Django V2.1 reverse is not a valid view function or pattern name

I am very new to Django and I have created two apps in my project one is login & server_status. I have used the namespace method to access my login and server_status across both apps. It is working fine when I tried to access index but when I tried to access dashboard in server_status it is not working.
Reverse for 'server_status' not found. 'server_status' is not a valid view function or pattern name
# server_status URL
from django.urls import path
from . import views
urlpatterns = [
path('', include('server_status.urls', namespace='server_status')),
path('', include('login.urls', namespace='login')),
path('admin/', admin.site.urls),
]
# login app URL
app_name = 'login'
urlpatterns = [
path('login', views.index, name='index')
]
# project URL
from django.contrib import admin
from django.urls import include, path
app_name = 'server_status'
urlpatterns = [
path('', views.index, name='index'),
path('dashboard/', views.dashboard, name='dashboard'),
path('server_status/', views.server_status, name='server_status'),
path('request_access/', views.request_access, name='request_access'),
]
In server_status/templates/server_status/index.html
Login
I know this is very simple one, but it makes me very complicated.
In the posted code, you define urlpatterns twice, so the first set of urlpatterns is overridden by the second. Since server_status is defined in the first set, it is not present in memory, since you obliterate it in the second definition. index is the only pattern that survives. I think what you meant to do in the second stanza was to add to the urlpatterns with:
urlpatterns += [...]
To declare namespace you should do something like this:
# project URL
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('', include('server_status.urls', namespace='server_status')),
path('', include('login.urls', namespace='login')),
path('admin/', admin.site.urls),
]
then you can use
Login
or
Server status index

Django Include() in urls.py with two apps

I believe this is a simple question but I am having a hard time figuring out why this is not working.
I have a django project and I've added a second app (sales). Prior to the second app, my urls.py simply routed everything to the first app (chart) with the following:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('chart.urls')),
]
and it worked fine.
I have read the docs over and over a looked at many tutorials, so my impression is that I can simply amend the urls.py to include:
urlpatterns = [
path('admin/', admin.site.urls),
path('sales/', include('sales.urls')),
path('', include('chart.urls')),
]
and it should first look for a url with sales/ and if it finds that then it should route it to sales.urls, and if it doesn't find that then move on and route it to chart.urls. However, when I load this and type in 127.0.0.1:8000/sales, it returns the following error:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/sales/
Raised by: chart.views.index
which tells me that it is not routing my sales/ url to sales.urls but to chart.urls. When I change path('', include('chart.urls')), to path('', include('sales.urls')), it does route it to sales.urls so I know that my sales.urls file is set up correctly.
I know this is probably an easy question but I cannot figure it out with anything I've read. Any help is appreciated.
chart.urls:
from django.urls import path, re_path
from . import views
urlpatterns = [
path('dashboard/', views.chart, name='dashboard'),
path('', views.index, name='index', kwargs={'pagename': ''}),
path('<str:pagename>/', views.index, name='index'),
]
sales.urls:
from django.urls import path
from . import views
urlpatterns = [
path('sales/', views.sales, name='Sales Dashboard'),
]
I think the correct url for the sales page in your case would be http://127.0.0.1:8000/sales/sales/.
This is because sales/ is then looking in the included sales.urls and not finding any urls at the root / (the only url included there is at sales/ (within sales/) so will be sales/sales/
Reply to an OLD question but may be useful for others...
from django.urls import path, include
dont for get to import include
Do this:
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('chart.urls')),
url(r'^sales/', include('sales.urls')),
]
you are not doing it properly since you are not telling your app where go once it is loaded .this r'^' to go directly to chart.url url(r'^', include('chart.urls')),

Categories

Resources