Django views confusion, two views show same content - python

I have a python django application. I had a view, which I duplicated and changed slightly to create a second view. But they seem to be hooked together and duplicate the page content, when they should be different.
Here is my urls.py
from django.urls import path, include
from django.contrib.auth import views as auth_views
from django.views.generic.base import RedirectView
from . import views
app_name = 'app'
urlpatterns = [
# Journals by Discipline
path('journals-by-discipline/', views.journals_by_discipline, name='journalsByDiscipline'),
path('journals-by-discipline/chart-data/<str:discipline>/', views.journals_by_discipline_chart_data),
path('journals-by-discipline/journals-and-disciplines-map/', views.get_journals_and_disciplines_map),
path('journals-by-discipline/disciplines-list/', views.disciplines_list),
# Journals By Discipline (Elsevier)
path('journals-by-discipline-elsevier/', views.journals_by_discipline_elsevier, name='journalsByDisciplineElsevier'),
path('journals-by-discipline/chart-data/<str:discipline>/', views.journals_by_discipline_chart_data_elsevier),
path('journals-by-discipline/journals-and-disciplines-map/', views.get_journals_and_disciplines_map),
path('journals-by-discipline/disciplines-list/', views.disciplines_list),
]
I have two views, journals_by_discipline and journals_by_discipline_elsevier
Here is my views.py
from django.shortcuts import get_object_or_404, render
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from rest_framework.decorators import api_view
from rest_framework.response import Response
import datetime as datetime
from dateutil.relativedelta import relativedelta
from urllib.parse import unquote
import json
from .onefigr_analysis import Data
# Instantiate Data object to fetch data across all views
data = Data()
# Journals by Discipline Page
def journals_by_discipline(request):
template_name = 'app/journals-by-discipline.html'
return render(request, template_name)
#api_view(['GET'])
def disciplines_list(request):
if request.method == 'GET':
return Response(data.get_disciplines_list())
#api_view(['GET'])
def journals_by_discipline_chart_data(request, discipline):
if request.method == 'GET':
query_discipline = unquote(discipline)
return Response(data.journals_by_discipline_chart_data(discipline))
#api_view(['GET'])
def get_journals_and_disciplines_map(request):
if request.method == 'GET':
return Response(data.journals_and_disciplines_map())
# Journals by Discipline Elsevier Page
def journals_by_discipline_elsevier(request):
template_name = 'app/journals-by-discipline-elsevier.html'
return render(request, template_name)
#api_view(['GET'])
def disciplines_list(request):
if request.method == 'GET':
return Response(data.get_disciplines_list())
#api_view(['GET'])
def journals_by_discipline_chart_data_elsevier(request, discipline):
if request.method == 'GET':
query_discipline = unquote(discipline)
return Response(data.journals_by_discipline_chart_data_elsevier(discipline))
#api_view(['GET'])
def get_journals_and_disciplines_map(request):
if request.method == 'GET':
return Response(data.journals_and_disciplines_map())
In my attempt to create the second view (journals by discipline elsevier), I duplicated the logic used to create the first view. But the result is both pages are the same.
In my Data() class, I have two methods: journals_by_discipline_chart_data and journals_by_discipline_chart_data_elsevier which are similar but not the same. I am trying to call these differently in my views.py file, but it is not working as it should.
How do I unhook these two views?

path('journals-by-discipline/', views.journals_by_discipline),
path('journals-by-discipline/chart-data/<str:discipline>/', views.journals_by_discipline_chart_data),
path('journals-by-discipline-elsevier/', views.journals_by_discipline_elsevier),
path('journals-by-discipline/chart-data/<str:discipline>/', views.journals_by_discipline_chart_data_elsevier),
The first route in each block is different (journals-by-discipline/ != journals-by-discipline-elsevier/). But the second route is the same (both journals-by-discipline/chart-data/<str:discipline>/).
So the route journals-by-discipline/chart-data/<str:discipline>/ will always call the function views.journals_by_discipline_chart_data. It will never reach the second time the route is mentioned.
You could change the second route in the second block to journals-by-discipline-elsevier/chart-data/<str:discipline>/ to be consistant.

Related

Specifying view function in Django

I'm practicing in Django and I want to know how requests and view mechanisms work correct in Django.
I started an app called ghcrawler in my django project. I designed like it has to send responses that recevied from localhost/ghcrawler and localhost/ghcrawler/results
So this is the urls.py in ghcrawler/ app folder.
from django.urls import path, include
from .views import main_view, results_view
urlpatterns = [
path('', main_view.as_view() , name='ghcrawler'),
path('ghresults', results_view.as_view(), name='getresults')
]
localhost/grcrawler page works well as expected. I just want to wire the requests coming to localhost/ghcrawler/results to getresults() function in results_view class defined in views.py, however it doesn't even write the 'h1' to the console
ghcrawler/views.py:
from django.views.generic import TemplateView
from django.shortcuts import render
from django import forms
from django.http import HttpResponse
from .github_requester import search_user
class main_view(TemplateView):
template_name = 'ghcrawler.html'
# Handle the post request received from /ghcrawler/
def post(self, request, *args, **kwargs):
if request.method == 'POST':
user = search_user(request.POST.get("username", ""))
if user == None:
print("User not found.")
else:
print(user)
return HttpResponse("OK")
class results_view(TemplateView):
template_name = 'ghresults.html'
def getresults(self, request, *args, **kwargs):
print('h1')
Rather than localhost/ghcrawler/results you mapped localhost/ghcrawler/ghresults to your view.
the rigth code would be:
urlpatterns = [
path('', main_view.as_view() , name='ghcrawler'),
path('results', results_view.as_view(), name='ghresults')
]
the firs argument in pathis the actual path
the secont argumen is the view
the third argument name is optional and used for addressing your view independant of your path
class results_view(TemplateView):
template_name = 'ghresults.html'
def get(self, request, *args, **kwargs):
print('h1')

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.

Django view not recognizing request

I have a form that is filled out on a webpage. The goal of the form is to gather some basic info, and then save the IP of the sender to the DB too. The form submits a POST request to my Django view, but Django gives me the error:
if request.method() == 'POST':
TypeError: 'str' object is not callable
Here is the view:
from .form import SignUpForm
from django.shortcuts import render
from django.http import HttpResponseRedirect
def index(request):
if request.method() == 'POST':
form = SignUpForm(request.POST)
if form.is.valid():
signup_item = form.save(commit=False)
signup_item.ip_address = request.META['HTTP_X_FORWARDED_FOR']
signup_item.save()
return HttpResponseRedirect(request.path)
else:
form = SignUpForm()
return render(request, 'index.html', {'form': form})
Here is the urls.py
from django.conf.urls.import url
from django.contrib import admin
from form import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', views.index, name='home')
]
I think the issue is with request.method(); method is a string data member, not a member function. Remember - this is python, where 'getters' are often dropped in favor of directly accessing class members.
So, try:
if request.method == 'POST':
form = SignUpForm(request.POST)
etc.

How to use initialize FormModel with request.post and model instance.

So I basically have this code:
#render_to('hello/home.html')
def home(request):
info = Info.objects.get(pk=1)
if request.method == "POST":
form = InfoForm(request.POST, instance=info)
else:
form = InfoForm(instance=info)
return {"info": info, "form": form}
aaand it doesn't work as I guessed it would be.
If I initialize form with ONLY either model instance or POST, it works, but not when both.
Is there a (nice?) way to create form with data populated from model instance, and update it with data from request.POST?
The code you are writing is already in the framework.
urls.py
from django.views.generic import UpdateView
from myapp.forms import InfoForm
urlpatterns = patterns('',
url(r'^info/(?P<pk>[-_\w]+)/update/$', UpdateView.as_view(model= Info,template_name="hello/home.html",form_class=InfoForm), name='info_update'),
)
# you might need to include a success url in the **kwargs i.e. success_url="/thankyou/"

reverse() is not working

I am trying to pass the id through reverse. But it's not working. I'm getting this error
Reverse for 'reg.views.thanks' with arguments '(20,)' and keyword arguments '{}' not found.
Here is my views.py:
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.core.urlresolvers import reverse
from reg.models import registration, registrationform
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
def registration(request):
if request.method == 'POST':
form = registrationform(request.POST)
if form.is_valid():
data = form.save()
id = data.id
return thanks(request,id)
else:
form = registrationform()
return render_to_response('registration.html', {'form' : form}, context_instance=RequestContext(request))
def thanks(request, id):
p = get_object_or_404(registration, pk=id)
return render_to_response('thanks.html', {'reg' : p})
Here is my urls.py:
from django.conf.urls import patterns, include, url
url(r'^registration/$', 'reg.views.registration'),
url(r'^thanks/$', 'reg.views.thanks'),
url(r'^$','django.views.generic.simple.direct_to_template', {'template' : 'index.html'}),
)
Here is thanks.html:
<html>
<body>
<p>Thank you for registration mr.{{reg.username}}</p>
</body>
</html>
and I'm also showing my models.py:
from django.db import models
from django.forms import ModelForm
class registration(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class registrationform(ModelForm):
class Meta:
model = registration
Thanks.
from this links (django tutorial):
https://docs.djangoproject.com/en/dev/topics/http/urls/#django.core.urlresolvers.reverse
example:
def myview(request):
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
so your code goes to:
in urls.py:
url(r'^thanks/(?P<id>\d+)$', 'reg.views.thanks', name='my_thanks_url')
in your function:
return HttpResponseRedirect(reverse('my_thanks_url', args=[id]))
This line
return HttpResponseRedirect(reverse('reg.views.thanks', args=(id,)))
Is trying to construct a url to your view reg.views.thanks, with the id variable used as a parameter.
This line in urls.py
url(r'^thanks/$', 'reg.views.thanks'),
Does not have anywhere for that parameter to go.
The first thing that you need to figure out is whether you actually want to send an HTTP redirect to the browser to tell it to go to the 'thanks' page. If you really do, then you need a way to send that id in the URL. You can do it as part of the URL path itself, as #moguzalp suggests, or you can put it in the query string, like
/thanks/?id=12345
Or you can do other things, like stashing the id in the user's session, and pulling it out when they request the thanks page. That's a bit more complicated, though.
If you don't actually need to issue an HTTP redirect, then there's nothing stopping you from just calling the thanks() function from inside your view function, like this:
def registration(request):
if request.method == 'POST':
form = registrationform(request.POST)
if form.is_valid():
data = form.save()
id = data.id
return thanks(request, id)
else:
form = registrationform()
return render_to_response('registration.html', {'form' : form}, context_instance=RequestContext(request))
The URL won't change in the browser, but the correct ID will be used, and doesn't need to appear anywhere else, in the URL, the query parameters, or the session

Categories