Django - calling function does not redirect - python

I want to redirect and return view after submiting form on my homepage. Unfortunately after POST nothing is happend.
My homepage:
def home(request):
if request.method == 'POST':
url = request.POST['url']
bokeh(request,url)
return render(request,'home.html')
def bokeh(request,url):
//my calculation logic
return render(request,'bokeh.html')
Of course I send other attributes like dictionaries etc, but it works fine when I hardcode my url in browser. After clicking submit on my form in my homepage nothing is happend.
EDIT
my bokeh function look like that:
def bokeh(request,url):
source = urllib.request.urlopen(url).read()
soup = bs.BeautifulSoup(source, 'lxml')
descrp = [description.text for description in soup.find_all('p', class_="commit-title")]
author = [author.text for author in soup.find_all('a', class_="commit-author")]
dict1 = dict(zip(descrp,author))
dict2 = dict(Counter(dict1.values()))
label = list(dict2.keys())
value = list(dict2.values())
plot = figure(title='Github Effort',x_range=label,y_range=(0,30), plot_width=400, plot_height=400)
plot.line(label,value,line_width = 2)
script,div = components(plot)
return render(request,'bokeh.html',{'script': script,'div': div})
and my urls.py
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^bokeh/(?P<url>\w+)/$',views.bokeh,name='bokeh',url='url'),
]
And at this moment I got TypeError: url() got an unexpected keyword argument 'url'

You did not return the result of the bokeh function:
def home(request):
if request.method == 'POST':
url = request.POST['url']
return bokeh(request,url)
return render(request,'home.html')
Note however that this is not redirecting, and therefore you do not implement the Post/Redirect/Get pattern [wiki]. In case of a successful POST request, it is usually a good idea to perform a redirect, to prevent a user from refreshing the page, making the same POST request. A POST request frequently has side effects, and therefore we want to omit that.
You better make use of the redirect(..) function [Django-doc] here:
from django.shortcuts import redirect
def home(request):
if request.method == 'POST':
url = request.POST['url']
return redirect('bokeh', url=url)
return render(request,'home.html')
You should not use a url=… in the url(..) function:
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^bokeh/(?P<url>\w+)/$', views.bokeh, name='bokeh'),
]

Related

Django redirect() doesn't redirect but rather refreshes the same page

view.py
#login_required(login_url='index', redirect_field_name=None)
def new_character(request):
if request.method == 'POST':
character_form = CharacterForm(request.POST)
if character_form.is_valid():
new_character = character_form.save(commit=False)
new_character.creator = request.user
new_character.save()
# If new_character has a primary key (pk) then it
# means it was saved to the database.
if new_character.pk:
# TODO: For some reason this doesn't work.
redirect('list_characters')
else:
character_form = CharacterForm()
return render(request, 'characters/new-character.html', {'character_form': character_form})
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.list_characters, name='list_characters'),
path('new/', views.new_character, name='new_character'),
]
I checked and new_character.pk is coerced to True. However, the redirect doesn't happen and instead the same page is simply refreshed.
The issue here is that you are not returning the redirect, which results in the return render(request, 'characters/new-character.html'... being hit, changing from:
redirect('list_characters')
To:
return redirect('list_characters')
Should solve the issue

How to order URLs in Django? I am getting `Page Not Found` error because of misplaced urls?

I am getting below error when I want to add a project or go to project_create URL.
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/project/add/
Raised by: projects.views.project_detail_view
the URL says /project/add/ that according to the view it must open project_create_view but the error is raised by detail view projects.views.project_detail_view.
This is the URL:
path('project/<slug:project_slug>/delete/',
project_delete_view, name='project_delete'),
path('project/<slug:project_slug>/update/',
project_update_view, name='project_update'),
path('project/<slug:project_slug>/',
project_detail_view, name='project_detail'),
path('projects/list/', all_projects_view, name='all_projects'),
path('project/add/', project_create_view, name='project_create'),
path('administration/', administration, name='administration'),
path("", home, name='home'),
if I comment this line path('project/<slug:project_slug>/',project_detail_view, name='project_detail'), then project_create URL goes to right view and right template. Why is this happening? I used different name, url and view name. Why is this happening?
Edit: I added both views
#login_required
def project_create_view(request):
if not request.user.is_superuser:
raise PermissionDenied
if request.method == 'POST':
form = ProjectForm(request.POST, request.FILES)
if form.is_valid():
title = form.instance.title
form.save()
project = get_object_or_404(Project, title=title)
messages.success(request, 'Project created successfully.')
return redirect(project.get_absolute_url())
form = ProjectForm()
return render(request, 'projects/project_create.html', {'form': form})
def project_detail_view(request, project_slug):
project = get_object_or_404(Project, slug=project_slug)
session_key = 'project_views{}'.format(project.slug)
if not request.session.get(session_key, False):
Project.objects.filter(id=project.pk).update(
visit_count=F('visit_count') + 1
)
request.session[session_key] = True
context = {
'project': project
}
return render(request, 'projects/project_detail.html', context)
Dynamic URLs must be on the bottom of the list,
urlpatterns = [
# Fixed URLs
path("", home, name='home'),
path('administration/', administration, name='administration'),
path('project/add/', project_create_view, name='project_create'),
path('projects/list/', all_projects_view, name='all_projects'),
# Dynamic URLs
path('project/<slug:project_slug>/',
project_detail_view, name='project_detail'),
path('project/<slug:project_slug>/delete/',
project_delete_view, name='project_delete'),
path('project/<slug:project_slug>/update/',
project_update_view, name='project_update'),
]
Ref: Django URL routing
You can order it by app, or by path, for example if you have more than one that starts with project you may group them in a different url pattern list.
projecturls =[
# your project path urls
]
urlpatterns =[
path('project/', include(projecturls)),
# ...
]

page opening even if not logged in, Django

I have made a small project.
User first logs in then he is redirected to the home page.
But if a user has not logged in then also that homepage is opening if we paste the url of that home page.
I have tried many things given on net but it's not working.
This is my urls.py
from django.conf.urls import url
from django.contrib import admin
from blog import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.login, name='login'),
url(r'^register/$', views.register, name='register'),
url(r'^home/$', views.home, name='home'),
url(r'^javaq/$', views.javaq, name='javaq'),
url(r'^javar/$', views.javar, name='javar'),
url(r'^csq/$', views.csq, name='csq'),
url(r'^csr/$', views.csr, name='csr'),
url(r'^cq/$', views.cq, name='cq'),
url(r'^cr/$', views.cr, name='cr'),
url(r'^cppq/$', views.cppq, name='cppq'),
url(r'^cppr/$', views.cppr, name='cppr'),
url(r'^pythonq/$', views.pythonq, name='pythonq'),
url(r'^pythonr/$', views.pythonr, name='pythonr'),
url(r'^mini/$', views.mini, name='mini'),
]
This is my view.py
from django.shortcuts import render
from .models import logininfo,CSTEST,CTEST,CPPTEST,JAVATEST,PYTHONTEST,result
from django.http import HttpResponse
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import cache_control
import datetime
def login(request):
if request.method=="POST":
user_name=request.POST.get("username")
sid=request.POST.get("sid")
password=request.POST.get("password")
article = logininfo()
article.user_name = user_name
article.sid = sid
article.password = password
article.save()
return render(request,'login.html')
def home(request):
if request.method=="POST":
sid=request.POST.get("sid")
password=request.POST.get("password")
request.session['sd'] = sid
user_obj=logininfo.objects.filter(sid=sid,password=password)
if user_obj.count()==0:
return HttpResponse("Sorry wrong password try again")
return render(request,'home.html')
def register(request):
return render(request,'register.html')
def javaq(request):
context = {
'query_results' : JAVATEST.objects.all()
}
return render(request, 'javaq.html',context)
def javar(request):
if request.method=="POST":
chosenOption = ''
correctAns = ''
c=0
x=1
for ans in JAVATEST.objects.all():
chosenOption=str(request.POST.get("java"+str(x)))
correctAns=str(ans.ANSWER)
if chosenOption==correctAns:
c=c+1
x=x+1
article = result()
article.sid = request.session['sd']
article.marks = c
article.subject = 'JAVA'
article.tdate = str(datetime.datetime.now())
article.save()
context = {
'query_results1' :c
}
return render(request, 'javar.html',context)
Add the #login_required decorator to your view function (the ones that render the pages that shouldn't appear to non logged in users).
You can have a broader idea about this decorator in this page.
You can use django built-in login-authentication on pages
#login_required(login_url='/url where you want user to redirect/')
def myview(request):
do something
return something #returns when user is logged in
Perhaps you should take a look at Django Stronghold.
Enable this in your settings, as per the instructions, and every view becomes private by default.
You can then decorate any functions which you want public access to like this:
#public
def register():
# Do something
This is probably the way to go for a beginner, as what you're doing just now (handling authentication logic in the home view) means you'll be repeating this for each separate view, and if you miss something, private parts of the app could end up public.

How do I add user data to url in Django?

I've got a function based view in Django called userView
#login_required(login_url='/login/')
def userView(request):
user = None
if request.user.is_authenticated():
user = request.user
user_id = user.pk
return render(request, "user_view.html", {'user': user})
and here's my URL for it
urlpatterns = [
url(r'^user/', userView, name='user'),
]
After my user has logged in, I'd like him to see his pk number in the URL. I.e., if the user's PK is 3 and the user directs their browser to www.myapp.com/user, the URL in the address bar should change to www.myapp.com/user/3/. How do I make that happen? I'm aware I need to edit the RegEx for the URL into
url(r'^user/(?P<user_id>[0-9]+)/$', userView, name='user')
but how do I pass the PK number to the URL?
I am not a Django expert but my guess is you want to redirect the user to his 'home page' after he is logged in. That can be done using the redirect() method
#login_required(login_url='/login/')
def userLoginView(request):
if request.user.is_authenticated():
return redirect("/user/{0}".format(request.user.pk), user=request.user)
And then define a second view that will render the home page
def userView(request, user_id=None, user=None):
return render(request, "user_view.html", {'user': user})
Also your url patterns should be as follows
urlpatterns = [
url(r'^user/', userLoginView, name='userlogin'),
url(r'^user/(?P<user_id>[0-9]+)/$', userView, name='user')
]

How to redirect with variables in django?

How to redirect with variables in django?
Please guide me, thank you.
urls.py:
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^computer/$', views.computer, name='computer'),
url(r'^result/$', views.result, name='result'),
)
This is my original views.py :
def computer(request):
result = Computer.objects.order_by('?')[:1]
return render(request, 'many/result.html',{'result':result})
And I found I problem, render will not redirect to moneymany/result.html on the url,
so if the user refresh, it will get another result on the same page.
So I have to use redirect to many/result.html .
What's the usually way to redirect in django and I have to pass variable result?
I try this,but not work :
def result(request):
return render(request, 'many/result.html')
def computer(request):
result = Computer.objects.order_by('?')[:1]
url = reverse(('many:result'), kwargs={ 'result': result })
return HttpResponseRedirect(url)
you need
url(r'^result/(?P<result>[^\/]*)/$', views.result, name='result'),
and
return redirect(reverse('many:result', kwargs={ 'result': result }))
or (without changing url)
return redirect('/result/?p=%s' % result )
if you want to maintain POST data while redirecting, then it means your design isnot good. quoting Lukasz:
If you faced such problem there's slight chance that you had
over-complicated your design. This is a restriction of HTTP that POST
data cannot go with redirects.
How about using redirect.
from django.shortcuts import redirect
def computer(request):
result = Computer.objects.order_by('?')[:1]
return redirect('view-name-you-want', { 'result'=result })
this worked with i just needed to pass url parameters as arguments
return redirect('pagename' ,param1 , param2)
my url looks like :
path('page', views.somefunction, name="pagename")
Note: in my case somefunction accept only POST parameters
To redirect from a view to another view with data, you can use session with request.session['key'] and in this case, you don't need to modify path() in "myapp/urls.py" as shown below. Then, give the conbination of the app name "myapp", colon ":" and the view name "dest_view" which is set in path() in "myapp/urls.py" as shown below:
# "myapp/views.py"
from django.shortcuts import redirect
def redirect_view(request):
# Here
request.session['person'] = {'name': 'John', 'age': 27}
# Here
return redirect("myapp:dest_view")
# "myapp/urls.py"
from django.urls import path
from . import views
app_name = "myapp"
urlpatterns = [ # This is view name
path('dest/', views.destination_view, name="dest_view")
]
Then, this is how you get the data of "post" method:
# "myapp/index.html"
{{ request.session.person.name }} {# John #}
{{ request.session.person.age }} {# 27 #}

Categories