How to provide a parameter to a router in django rest API? - python

So the url I am trying to achieve looks like this:
127.0.01:8000/api/tech/?belongs=id
My router looks like this:
router = routers.DefaultRouter()
router.register('tech', TechViewSet, basename="tech")
urlpatterns = [
path('', include(router.urls)),
re_path(r'^tech/(?P<belongs>)$', include(router.urls), name="info"),
My viewset looks like this (Also has a retrieve and list functions):
#action(detail=True, url_path='^tech/(?P<belongs>)$', methods=['get'])
def retrieve1(self, request, group=None):
pass
And the router is obviously included in urls.py of main project
How to get this url working.. 127.0.01:8000/api/tech/?belongs=id
Please help. and Im sorry, I'm still learning and the routing part is confusing..
Thankyou so much

It's a little tricky without knowing your model structure. But if you're using your get parameters for filtering you can use django_filters to do the heavy lifting for you. Something like this:
pip install django-filter
add this to your rest framework settings:
'DEFAULT_FILTER_BACKENDS':['django_filters.rest_framework.DjangoFilterBackend']
Then in your TechViewSet you can add filterset_fields:
class TechViewSet:
<your other variables>
filterset_fields = ['belongs',]
you can then add query parameters ?belongs=<some_id> to your url and your results will be filtered.
docs:
https://www.django-rest-framework.org/api-guide/filtering/#djangofilterbackend

Related

Django settings LOGIN_REDIRECT_URL dynamic based on language

Let's say I have LOGIN_REDIRECT_URL='/foo/bar/' and I am on http://127.0.0.1/en/login/ and I login successfully. I will be redirected to http://127.0.0.1/foo/bar/ resulting in losing the language prefix. What should I do in order to maintain the language code in the url? Of course, I want all the other languages codes work and also the default one just like that:
http://127.0.0.1/en/login/ -> http://127.0.0.1/en/foo/bar/
http://127.0.0.1/login/ -> http://127.0.0.1/foo/bar/
http://127.0.0.1/ro/login/ -> http://127.0.0.1/ro/foo/bar/
In that case you can extend Django's LoginView and override the get_success_url method.
Something like this:
from django.contrib.auth.views import LoginView
from django.utils.translation import get_language
class CustomLoginView(LoginView):
def get_success_url(self):
# lang = get your language from the URL (it'd be helpful if you post your URLs in order to help better) or you can use like this:
lang = get_language()
url = '{}/{}/login'.format(yourbaseurl, lang)
return url
Assuming you are using Django auth and the LoginView from the framework, you can parametrize the URL to redirect to after logging in. The LOGIN_REDIRECT_URL is a fallback when it is not specified.
The LoginView attribute is called next. The next url can be set using a parameter from the previous page like ?next=<your_url>. Just don't forget to sanitize it using is_safe_url() from django.utils.http.

How can I configure category, subcategory and posts with slug in Django urls.py?

I need to configure Django urls like this:
/<slug_category>/
/<slug_category>/<slug_sub_category>/
/<slug_category>/<slug_post>/
I've tried this. The problem is that the /<slug_category>/<slug_sub_category>/ and /<slug_category>/<slug_post>/ give conflict.
urlpatterns = [
url(r'^(?P<category_slug>[\w-]+)$', views.category),
url(r'^(?P<category_slug>[\w-]+)/(?P<slug_subcategory>[\w-]+)/$', views.category),
url(r'^(?P<category_slug>[\w-]+)/(?P<post_slug>[\w-]+)/$', views.post),
]
Is it possible to do that? Can someone help me?
Thanks!
You cannot use two different URLs because they have the same pattern (as has been pointed out in the comments). The solution is to use the same URL and to fetch the content accordingly. For example
urlpatterns = [
url(r'^(?P<category_slug>[\w-]+)$', views.category),
url(r'^(?P<category_slug>[\w-]+)/(?P<slug_subcategory>[\w-]+)/$', views.cat_or_post),
]
And then you have a function that will try to fetch a post and if that fails pass it to views.category. Something like this:
def cat_or_post(request,category_slug,slug_subcategory):
try:
post = Post.objects.get(slug=slug_subcategory)
# put the rendering code here
except Post.DoesnotExist:
return category(request,category_slug,slug_subcategory)

Django logout() returns none

Morning everyone
Im using django logout() to end my sessions just like django docs says :
views.py
class Logout(View):
def logout_view(request):
logout(request)
return HttpResponseRedirect(reverse('cost_control_app:login'))
and im calling it from this url :
urls.py
url(r'^logout/$', views.Logout.as_view(), name = "logout"),
Buttttttt it's not working, when i do a trace i find that the function :
def logout_view(request):
it's returning "none" and it's nos entering to execute the code inside...
Please help me !
I'm curious, why do you have the method named logout_view()? By default, nothing is going to call that method. You need to change the name to match the HTTP verb which will be used to call the page. For instance, if it's going to be a GET request, you would change it to:
def get(self, request):
If you want it to be a POST request, you would change it to:
def post(self, request):
This is the standard way that class-based views work in Django. Also, you may want to look at the documentation for class-based views, as this may give you a better idea of their workings and what they can provide to you. (Hint: There is a built-in RedirectView)
Django has a built in logout view. I would use that rather than writing your own.
from django.contrib.auth import views as auth_views
from django.core.urlresolvers import reverse_lazy
url(r'^logout/$',
auth_views.logout,
{'next_page': reverse_lazy('cost_control_app:login')},
name='logout',
)
If you want to write your own logout view, then I would stick with a function based view. There's no need to use a class based view here. The docs on logging a user out have an example.
def logout_view(request):
logout(request)
# Redirect to a success page.
Then change the url pattern to
url(r'^logout/$', logout_view, name="logout"),
If you really want to write a class based view, then you need to fix your Logout view. See Joey's answer for more info about this.
Solved it, i just removed the class logout(View) and call the def from the url without the "as_view" and it works. Thanks to all !

How to read parameters from request in django

I need to read some parameters being passed in and perform some action in django. How can I do that.
url = 172.15.20.116/request
and server is requesting with below parameters
url = 172.15.20.116/request/1289/
here 1289 is parameter. How to parse it?
To so this you need to capture this in the urls.
You will need to look into the django url dispatcher this page has pretty much everything you need to get started. Take your time, learn and then implement.
Maybe something like:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^request/(?P<id>\d+)/$', 'appname.views.my_request_view'),
]
views.py
def my_request_view(request, id):
... # logic goes here

Django: How do I create a generic url routing to views?

I have a pretty standard django app, and am wondering how to set the url routing so that I don't have to explicitly map each url to a view.
For example, let's say that I have the following views: Project, Links, Profile, Contact. I'd rather not have my urlpatterns look like this:
(r'^Project/$', 'mysite.app.views.project'),
(r'^Links/$', 'mysite.app.views.links'),
(r'^Profile/$', 'mysite.app.views.profile'),
(r'^Contact/$', 'mysite.app.views.contact'),
And so on. In Pylons, it would be as simple as:
map.connect(':controller/:action/:id')
And it would automatically grab the right controller and function. Is there something similar in Django?
mods = ('Project','Links','Profile','Contact')
urlpatterns = patterns('',
*(('^%s/$'%n, 'mysite.app.views.%s'%n.lower()) for n in mods)
)
Unless you have a really huge number of views, writing them down explicitly is not too bad, from a style perspective.
You can shorten your example, though, by using the prefix argument of the patterns function:
urlpatterns = patterns('mysite.app.views',
(r'^Project/$', 'project'),
(r'^Links/$', 'links'),
(r'^Profile/$', 'profile'),
(r'^Contact/$', 'contact'),
)
You might be able to use a special view function along these lines:
def router(request, function, module):
m =__import__(module, globals(), locals(), [function.lower()])
try:
return m.__dict__[function.lower()](request)
except KeyError:
raise Http404()
and then a urlconf like this:
(r'^(?P<function>.+)/$', router, {"module": 'mysite.app.views'}),
This code is untested but the general idea should work, even though you should remember:
Explicit is better than implicit.

Categories