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')
Related
I am looking to redirect my user to login page, if they have not logged in.
I initally looked at the decorator #login_required(login_url='/accounts/login/').
But this is not ideal, for 2 reasons: first I want this to apply to all views. Also the decorator returns an error message when I try to login with allauth.
I am sure this is solvable, but I am looking for a solution that could apply to all views.
I found something using authmiddleware(doc: https://pypi.org/project/django-authmiddleware/). However the code doesn't not seem to be responsive, in the sense nothing is happening and the logs on the console don't seem to pick up anything.
Can someone see what I am doing wrong?
base.py
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'AuthMiddleware.middleware.AuthRequiredMiddleware',
]
AUTH_SETTINGS = {
"LOGIN_URL" : "login_user",
"DEFAULT_REDIRECT_URL" : None,
"REDIRECT_AFTER_LOGIN" : False,
}
views.py
from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import authenticate, login, logout, get_user_model
from django.urls import reverse
def list_event(request): #ADDED FOLLOWING REQUEST IN COMMENTS
event_list = Event.objects.all
return render(request, 'main/list_event.html',{'event_list':event_list})
class AuthRequiredMiddleware(object):
def process_request(self, request):
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('login_user'))
return None
Found an alternative solution and thought I would leave it there.
I used a tutorial on youtube (https://www.youtube.com/watch?v=axsaC62UQOc) which, with a few changes (the video is old), works like a charm. Its about 3 videos 30 minutes very well explained.
Here it goes:
settings.py
MIDDLEWARE = [
'[yourappname].middleware.LoginRequiredMiddleware',
]
LOGIN_EXEMPT_URLS =( #<-- I am using allauth, so left some examples here)
r'logout',
r'register_user',
r'accounts/google/login/',
r'accounts/social/signup/',
r'accounts/facebook/login/',
)
middleware.py (this files goes in your main app, by default "mysite")
import re
from django.conf import settings
from django.shortcuts import redirect
EXEMPT_URLS = [re.compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [re.compile(url) for url in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware:
pass
def __init__(self, get_response):
self.get_response = get_response
def __call__ (self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
assert hasattr(request,'user')
path = request.path_info.lstrip('/')
print(path)
if not request.user.is_authenticated:
if not any(url.match(path) for url in EXEMPT_URLS):
return redirect(settings.LOGIN_URL)
why not use
return redirect('%s?next=%s' % (settings.login_user, request.path))'
instead of HttpResponse?
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.
I'm leaning Python to develop a website. I use Django framework to develop. To create a VIEW using django.views.generic.base.TemplateView.
So I wanna to get value 'user_name' and 'mail' from URL, but don't know how to do that! I cannot import request within this view.
Here is Views.py:
from django.views.generic.base import TemplateView
class MainView(TemplateView):
template_name = 'guestbook/main_page_1.html'
def get_context_data(self, **kwargs):
#I wanna to get value 'user_name' and 'mail' from URL...
name = request.GET.get("user_name") #temp
email = request.GET.get("mail") #temp
context = super(MainView, self).get_context_data(**kwargs)
context['var1'] = name
context['var2'] = email
return context
Here is Urls.py:
from django.conf.urls import patterns, url
from guestbook.views import MainView
urlpatterns = patterns('',
url(r'^$', MainView.as_view(), name='main'),
)
Anybody can help me to do this!
Thanks all!
Request is available in get_context_data() as self.request:
def get_context_data(self, **kwargs):
name = self.request.GET.get("user_name")
email = self.request.GET.get("mail")
...
How does one redirect from one View to another (next-going one):
class FooView(TemplateView):
template_name 'foo.html'
def post(self, *args, **kwargs):
return redirect(BarView)
# return redirect(BarView.as_view()) ???
class BarView(TemplateView):
template_name 'bar.html'
Give the URL pattern itself a name in your urls.py:
url('/bar/', BarView.as_view(), name='bar')
and just pass it to redirect:
return redirect('bar')
You can use the redirect for that, if you've given the view a name in urls.py.
from django.shortcuts import redirect
return redirect('some-view-name')
You need to give the view name "bar" to the path in "myapp/urls.py" as shown below:
# "myapp/urls.py"
from django.urls import path
from . import views
app_name = "myapp"
urlpatterns = [ # This is view name
path('bar/', views.BarView, name="bar")
]
Then, you need the conbination of the app name "myapp", colon ":" and the view name "bar" as shown below. In addition, you don't need to import the view "bar" in "myapp/views.py":
# "myapp/views.py"
from django.shortcuts import redirect
def FooView(request):
# Here
return redirect("myapp:bar")
def BarView(request):
return render(request, 'myapp/index.html', {})
I don't want to have the day in the URL for a detail view while using Django's dated_based generic views. I tried the following but get a TypeError at /logbook/2013/january/testing/ object_detail() takes at least 6 arguments (7 given):
models.py
class Entry(models.Model):
pub_date = models.DateTimeField()
def get_absolute_url(self):
return "/logbook/%s/%s/" % (self.pub_date.strftime("%Y/%B").lower(), self.slug)
urls.py:
from __future__ import absolute_import
from django.conf.urls import patterns, include, url
from .models import Entry
from . import views
urlpatterns += patterns('',
url(r'^logbook/(?P<year>\d{4})/(?P<month>[A-Za-z]+)/(?P<slug>[\w-]+)/$',
views.entry_detail),
)
views.py:
import functools
from django.views.generic import date_based
from .models import Entry
def prepare_arguments(view):
#functools.wraps(view)
def wrapped(request, *args, **kwargs):
kwargs['allow_future'] = request.user.is_staff
kwargs['queryset'] = Entry.objects.all() if request.user.is_staff
else Entry.objects.published()
kwargs['date_field'] = 'pub_date'
return view(request, *args, **kwargs)
return wrapped
#prepare_arguments
def entry_detail(request, *args, **kwargs):
return date_based.object_detail(request, *args, **kwargs)
Is it possible to modify the code above and continue to use the date_based generic view without the day in the URL? If not, can someone please give an example of a simple custom view for the URL pattern url(r'^logbook/(?P<year>\d{4})/(?P<month>[A-Za-z]+)/(?P<slug>[\w-]+)/$', views.entry_detail)?
Thanks to Alasdair for pointing me in the right direction and to ccbv.co.uk. I ended up using DetailView and this worked:
urls.py:
from django.views.generic import DetailView
urlpatterns += patterns('',
url(r'^logbook/(?P<year>\d+)/(?P<month>[-\w]+)/(?P<slug>[\w-]+)/$',
DetailView.as_view(model=Entry),
name="entry_detail"),
)
views.py:
# nothing needed here for the detail view to work, though in the future
# I would like to have the generic view code here instead to accomplish
# the same thing as `DetailView.as_view(model=Entry), name="entry_detail"`
# in urls.py, and would appreciate an example of this.