How to pass url value in django to views - python

My url.py is as below,
from myapp import views
urlpatterns = [
url(r'^myapp/get_requests/$', views.get_requests),
]
Now my views.py is as below,
#api_view(['GET'])
def get_request(request):
#How can I get request ID (base url here)?
return HttpResponse('test')
In the above if I do request in my browser with url as below it reaches my get_request method,
http://localhost:8080/myapp/get_requests/
But the same gives error 404 when I try with some ID in the end as below,
http://localhost:8080/myapp/get_requests/40
Now How can I get this ID number 40 in my views.py method?

Change your urls.py to
from myapp import views
urlpatterns = [
url(r'^myapp/get_requests/(?P<id>[0-9]+)$', views.get_requests),
]
Now get the id parameter in your views like this
#api_view(['GET'])
def get_request(request,id):
print id
return HttpResponse('test')
For more information check out django docs

If you want to pick up id from url, you just have to write something like this :
#login_required
def MyFunction(request, id) :
myobject = get_object_or_404(MyModel, pk=id)
context = {
"myobject" : myobject,
}
return render(request, 'my template.html', context)
And your url, you have to add url(r'^myapp/get_requests/(?P<id>\d+)/$', views.get_requests),
I assume your url is correct and he's already created with id inside. So I just gave you How I pick up object according to this ID.

There is a typo in the view function name in your above code. So, it would be get_requests not get_request.
Now coming to your question, it throws you 404 - Not Found because there is no actual route that you've defined that should expect the id after the url.
To start accepting id, add another route for it in your urls.py which has a digit regext like:
from myapp import views
urlpatterns = [
url(r'^myapp/get_requests/$', views.get_requests),
url(r'^myapp/get_requests/(?P<id>\d+)$', views.get_requests_with_id),
]
and in your views.py, define the view function to accept id parameter something like this:
#api_view(['GET'])
def get_requests_with_id(request, id):
# Now use id for whatever you want
return HttpResponse('test')
You can read about it form the official documentation here: https://docs.djangoproject.com/en/1.11/topics/http/urls/#named-groups

Related

Empty `request.user.username` while handling a GET request created

I was trying out logging all URLs accessed by user along with user id and date time when it was accessed using django middleware as explained here.
For some URLs it was not logging user id. I checked and found that the request.user.username was empty string. I checked views corresponding to those URL and found that those views did not have desired decorators. For example, I changed this:
def getXyz_forListView(request):
# view body ...
to this:
#api_view(['GET'])
#authentication_classes([TokenAuthentication,])
def getXyz_forListView(request):
# view body ...
and it started working.
However some views are created from classes:
class XyzView(View):
def get(self, request):
# view body ...
I added same decorators:
class XyzView(View):
#api_view(['GET'])
#authentication_classes([TokenAuthentication,])
def get(self, request):
# view body ...
But it is still not working. What I am missing?
PS:
It is added to urls.py as follows:
urlpatterns = [
# ...
url(r'^xyz/', XyzView.as_view(), name="xyz"),
]
I think you should try to inherit from APIView class:
from rest_framework.views import APIView

How to send url as slug field into url in Django

I have my urls.py as this:
from django.urls import path
from . import views
urlpatterns = [
path('link',views.get_text,name='text'),
path('link/<link>',views.show,name='show')
]
When I enter a url like http://127.0.0.1:8000/link/https://www.geeksforgeeks.org/gate-cs-notes-gq/, it is showing page not found as it is checking the / in the slug url. I am storing the url and other fields in database, so I want to retrieve the database objects using the url. How to do such that when I enter a url in the browser, it takes the entire url as link field in urls.py , so that I can retrieve the db objects from views.py in this way:
def show(request,link):
objs = Links.objects.filter(link=link).values()
return HttpResponse('link')
Pass the URL in the querystring of the requesting URL: http://127.0.0.1:8000/link/?link=https://www.geeksforgeeks.org/gate-cs-notes-gq/
The data from the querystring is available in the request.GET dictionary in your view
def link_view(request):
if 'link' in request.GET:
objs = Links.objects.filter(link=request.GET['link']).values()
return HttpResponse(...)
else:
# Handle no link provided (views.get_text)
Your url patterns then only need to define one path that handles both cases where a URL is provided or not
urlpatterns = [
path('link/', views.link_view, name='link_view'),
]
To redirect, you can use HttpResponseRedirect. It will redirect the url without specifying the view. It you write HttpResponseRedirect('/link'), it will redirect you to http://127.0.0.1:8000/link. Since you mentioned, redirect from another view, you do in this way:
def link_view(request):
if 'link' in request.GET:
objs = Links.objects.filter(link=request.GET['link']).values()
return HttpResponse(...)
else:
# do something when no link provided (views.get_text)
return HttpResponseRedirect('/link?'+str(link))#str(link) is the url you want to get

How to exit views function if queryset not found not found in database

I have two apps in my django project "card" and "blog"
my project urls.py is :
urlpatterns = [
path('admin/', admin.site.urls),
path(r'', include(card.urls)),
path('', include('blog.urls')),]
url.py for "card" app is:
urlpatterns = [
re_path(r'^card/$', views.cardindex, name='cardindex'),
re_path(r'^(?P<card_url_var>[-\w.]+)/$', views.carddet, name='carddetail'),]
views.py for "card" app is:
def cardindex(request):
....
def carddet(request, card_url_var):
try:
url_carddetails = carddata.objects.get(page_end_url=card_url_var)
except carddata.DoesNotExist:
raise Http404("Card you are looking for, does not exists")
return render(request, 'card.html', {'url_carddetails':url_carddetails})
Now urls.py for "blog" apps is:
urlpatterns = [
re_path(r'^blog/$', views.articleindex, name='articleindex'),
re_path(r'^(?P<art_url_var>[-\w.]+)/$', views.articledet, name='articledetail'),]
viws.py for blog apps is:
def articleindex(request):
....
def articledet(request, art_url_var):
try:
url_articledetails = articledata.objects.get(art_end_url=art_url_var)
except articledata.DoesNotExist:
raise Http404("Article you are looking for, does not exists")
return render(request, 'article.html', {'url_articledetails':url_articledetails})
When I request urls that are in "page_end_url" column of "carddata" model the code works fine. But when I request urls that are in "art_end_url" column of "articledata" model it returns Http404 "Card you are looking for, does not exists".
For Example:
If I request example.com/new-year-card-2018
The Code works fine because "new-year-card-2018" exists in "page_end_url" column.
But If i request example.com/best-designs-of-2018
The url "/best-design-of-2018" whis is saved "art_end_url" attribute of "articledata" model. The code returns Http404 "Card you are looking for, does not exists"
So please tell me that, is there is way to exit carddet function in "card" views.py file, if requested url i.e "card_url_var" does not match with "page_end_url".
I am a newbie in django.
Any suggestions would be helpful. Thanks in Advance
You request keeps calling the first URL matches from your URLs patterns.
Actually, these 2 URLs are almost same:
re_path(r'^(?P<card_url_var>[-\w.]+)/$', views.carddet, name='carddetail'),]
re_path(r'^(?P<art_url_var>[-\w.]+)/$', views.articledet, name='articledetail'),]
This (?P<card_url_var>[-\w.]+) is waiting for a slug : /slug-slug/
And also this (?P<art_url_var>[-\w.]+): /slug-slug/.
So Django will look for the first match URL, obviously the first will match. What you can do is add something different in each, like:
re_path(r'^card/(?P<card_url_var>[-\w.]+)/$', views.carddet, name='carddetail'),]
re_path(r'^article/(?P<art_url_var>[-\w.]+)/$', views.articledet, name='articledetail'),]
you can try in this way.
from django.core.urlresolvers import reverse
try:
...
except:
return redirect(reverse('name-of-url'))
more details here

Django Urls - two views with same regular expression

I have two views with the same regular expression, as you can see below. It's a Category and an Article view, their entry slugs will never be the same so it should be no problem. But at the moment it doesn't work well, as you prolly know the category-view will get triggered.
Please do not suggest to make the url structure unique, the slugs of categories and articles will never be the same. It should be as short as possible.
urls.py
urlpatterns = [
url(r'^index', index.Index.as_view(), name='index'),
url(r'^search', search.Index.as_view(), name='search'),
url(r'^(?P<slug>.+)$', category.Index.as_view(), name='category'),
url(r'^(?P<slug>.+)$', article.Index.as_view(), name='article'),
]
I tried to reverse from views.category back to urls.py if there is no category to find like this:
views.category.py
class Index(View):
def get(self, request, slug):
category = CategoryModel.objects.get(slug=slug)
if category is None:
return HttpResponseRedirect(reverse('article', args=[slug]))
context = {
'category': category
}
return render(request, 'category/index.html', context)
The error (but there is a article with slug 'test123'):
NoReverseMatch at /wiki/test123
Reverse for 'article' with arguments '('test123',)' and keyword arguments '{}' not found. 0 pattern(s) tried: []
Using Python 3.6
Why dont you try differentiating the URLs like so
urlpatterns = [
url(r'^index', index.Index.as_view(), name='index'),
url(r'^search', search.Index.as_view(), name='search'),
url(r'^category/(?P<slug>.+)$', category.Index.as_view(), name='category'),
url(r'^article/(?P<slug>.+)$', article.Index.as_view(), name='article'),
]
You get to use the same regular expressions without the URL being ambiguous.
You can remove the article.Index view and rather than trying to redirect when there's no object for Category, you can call the method you defined in article.Index with the same parameters as the get method takes in article.Index view.
Example:
urls.py
urlpatterns = [
url(r'^index', index.Index.as_view(), name='index'),
url(r'^search', search.Index.as_view(), name='search'),
url(r'^(?P<slug>.+)$', category.Index.as_view(), name='category'),
# article url removed
]
views.category.py
from path.to.article import Index as ArticleIndexView
class Index(View):
def get(self, request, slug):
category = CategoryModel.objects.get(slug=slug)
if category is None:
# calling article app's Index get method
article_index_view_obj = ArticleIndexView()
return article_index_view_obj.get(request, slug)
context = {
'category': category
}
return render(request, 'category/index.html', context)
If you make the article.Index class view as function-based view.
You can import from path.to.article import index as article_index
and then, instead of instantiating the object, you can directly call article_index(request, slug).
There are several issues here.
(1) You call reverse with args but you have specified a kwarg.
if category is None:
return HttpResponseRedirect(reverse('article', args=[slug]))
Reverse for 'article' with arguments '('test123',)' and keyword arguments '{}' not found.
Says exactly that - as you did not provide the keyword argument, it could not find the matching URL pattern. This would be correct:
if category is None:
return HttpResponseRedirect(reverse('article', kwargs={'slug':slug}))
(2) You will end up in that same code again and again - is what I expect to happen once you fix (1). Because if reverse really does reverse the URL - the result of reverse will of course also match the category URL which means it will simply call the category.Index view - again.
I think your URL setup could actually work because the resolver does try all URLs sequentially until one comes along that matches. I'm just not sure if you can make the view return something that will lead to the URL resolver to kick in and decide to take the next URL (article) instead of category which just resolved. Probably not.
In this case, if you are fine with redirects, you could just define 3 URL patterns. 1 for the view that will operate as a switch and redirect to the CategoryView or ArticleView respectively.
Otherwise go with Sachin Kukreja's solution of handling both in one view.
Finally I made it like this. Actually I wanna use 2 different views but I guess it's fine too. Does someone see a mistake?
class Index(View):
def get(self, request, slug):
self.request = request
self.slug = slug
self.item = None
is_article = ArticleModel.objects.filter(slug=self.slug).exists()
if is_article:
self.item = 'article'
return self.article()
is_category = CategoryModel.objects.filter(slug=self.slug).exists()
if is_category:
self.item = 'category'
return self.category()
self.item = None
# 404 here
return HttpResponse(self.item)
def article(self):
article = ArticleModel.objects.get(slug=self.slug)
context = {
'article': article
}
return render(self.request, 'article/index.html', context)
def category(self):
category = CategoryModel.objects.get(slug=self.slug)
context = {
'category': category
}
return render(self.request, 'article/index.html', context)

How to call a specific url from Django views?

I want to make a call to specific url pattern from Django Views.
The call should be inside first IF conditional and outside the inner if. Is the any function which provides redirection? Or something like redirect(map_vertical_crawl)? The code portion for
Django Views:
def add_vertical(request):
if request.method == 'POST':
form = VerticalForm(request.POST)
if form.is_valid():
form.save()
#I WANT TO CALL URL EXACTLY AT THIS POINT, INSIDE OUTER IF.
verticals = Verticals.objects.all()
return render(request, 'cfman/add_vertical.html',
{'form': VerticalForm(),
'verticals': verticals}
)
Django URLS:
from django.conf.urls import url
from . import views, apps
urlpatterns = [
#Generates Login Screen
url(r'^$', views.LoginView.as_view(), name="login"),
#Directs to manager view level 1
url(r'^manager/$', views.verticals_view, name="manager"),
#Directs to manager view level 2
url(r'^manager/(?P<verticalid>\d+)/$', views.source_list, name='source_list'),
#Add Vertical
url(r'^verticals/add_vertical/$', views.add_vertical, name="add_vertical"),
#Add Source
url(r'^sources/add_source/$', views.add_source, name="add_source"),
#Add Crawl Type
url(r'^crawls/add_crawl/$', views.add_crawl, name="add_crawl"),
#Map verticals and crawl types
url(r'^vertical_crawl/$', views.map_vertical_crawl, name="map_vertical_crawl"),
]
I want to call the last url pattern , 'map_vertical_crawl' from views.
Django's built-in redirect() accepts a view name as parameter, so just do:
redirect('cfman:map_vertical_crawl')

Categories