Check for password before accessing content in django - python

I am trying to build a functionality where users have to enter the passcode to access the site.
If you go to this site it will ask for a password (123) before showing you the content:
https://www.protectedtext.com/djangoproj
I want to do it without forms.py.
URL OF THE PAGE --> TEMPLATE --> ASK FOR PASSCODE --> SHOW CONTENT IF PASSCODE MATCHES
models.py
from django.db import models
# Create your models here.
class Text(models.Model):
text = models.TextField(blank=True)
slug = models.SlugField(unique=True)
password = models.CharField(max_length=50)
def __str__(self):
return self.slug
views.py
from django.shortcuts import render
from .models import Text
import django.contrib.auth
# Create your views here.
def textview(request, slug):
obj= Text.objects.get(slug=slug)
return render(request, 'text/textpage.html', {'obj' : obj})
def home(request):
return render(request, 'text/index.html', {})
I have tried creating a new template for password but I am still not getting that functionality.
Thanks in advance

If I were you (and didn't want to use DRF), I would make something like this:
def check_password(*args, **kwargs): # decorator function for checking password
def wrapper(func):
if kwargs.get('password', None) == '123':
func() # show index, if password is corrent
else:
raise Exception('Access denied') # else raise the exception
return wrapper
def home(request):
try:
password = request.GET.get('password') # get password from given parameters
#check_password(password)
def show_index(): # create function, maybe better to make it out of scope
return render(request, 'text/index.html', {})
show_index() # call function
except:
print('Password was not given or it is incorrect, access denied')
return render(request, 'text/401.html', {})

Related

Passing Id and Context in Django Redirect

I want to pass a model to a html page as context when I login into an account.
My Home page url comes with user id as a url parameter.
But i cant pass any context in redirect
views.py
from django.contrib.auth import authenticate,login,logout
from django.contrib import messages
from django.shortcuts import redirect, render
from django.http import HttpResponse
from .models import users
from home.models import Posts
def f1(request):
Post = Posts.objects.all()
context = {'Post':Post}
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
uz = authenticate(request,username=username, password=password)
if uz is not None:
login(request,uz)
id = users.objects.filter(name=username).values('id')[0]['id']
return redirect('home',id) # This Works Fine
return redirect('home',id,context) # This is not Working
else:
messages.error(request,"Wrong Credentials")
return render(request,'login.html')
urls.py
from django.contrib.auth import logout
from django.urls import path
from . import views
urlpatterns=[
path('<str:users_id>/',views.func,name="home"),
]
How can I pass the context?
If I can't tell me an alternative way to do it.
You're redirecting to another view, so you're passing data through your url. You can't put your context in it, so you can directly render your template :
return render(request, "home.html", context)
If you really want to redirect to another url, as your context only contains all Post objects, you can build it in your home view.
Then you have :
f1 :
return redirect('home',id)
func :
context = {'Post': Posts.objects.all()}
return render(request, "home.html", context)
Add the id to your context dictionary and pass to redirect. Something like
context = {'Post':Post, 'Id':id}
return redirect('home', context)
#Balizok is correct: you can't pass context via the URL, without urlencoding it, which would be a bad idea for large amounts of data. If you need the home page to show posts or not show posts depending on whether the user has just logged in, you could do it in a few ways:
Show posts only if the user is logged in:
def home(request, id):
context = {}
if request.user.is_authenticated:
context["Post"] = Posts.objects.all()
return render(request, "home.html", context)
Show posts only if the user has just been redirected from the login page via a query parameter:
from django.url import reverse
def f1(request):
# ... log the user in etc.
url = reverse("home", id) + "?show_posts=true"
return redirect(url)
def func(request, id):
context = {}
if request.GET.get("show_posts") == "true":
context["Post"] = Posts.objects.all()
return render(request, "home.html", context)
Show posts only if the user has just been redirected from the login page via the session:
from django.url import reverse
def f1(request):
# ... log the user in etc.
request.session["show_posts"] = True
return redirect("home", id)
def func(request, id):
context = {}
if request.session.get("show_posts"):
context["Post"] = Posts.objects.all()
return render(request, "home.html", context)

Why am I getting an AttributeError?

I'm trying to store the first name and last name of a user in my datatbase upon hitting the submit button so that next time when I manually check in Terminal what's inside my database, I can see exactly what the user inputted.
This is the error I'm getting:
I'm assuming the error is coming from my views.py file:
from django.http import HttpResponse
from .models import Person
from django.shortcuts import render
def index(request):
if request.method == 'POST':
first_name = request.POST.get('firstName')
last_name = request.POST.get('lastName')
if first_name and last_name:
user = Person.objects.create(firstName=first_name, lastName=last_name)
user.save()
return render('request', 'music/index.html')
def detail(request, user_id): # Testing out page 2
return HttpResponse("<h2>Page # (testing this out) " + str(user_id) + "</h2>")
The code is passing 'request' (string literal) to django.shortcuts.render which expected Request object as the first parameter.
Pass the request parameter of the view function:
return render('request', 'music/index.html')
should be:
return render(request, 'music/index.html')

Django Model Authorisation

In my Django app, I've some CRUD operations over some models, which I want to be accessed only by the user who created that row. Here it's not role based authorisation as all users are same, I want them to be identified by the user who created it.
I tried something like:
class someModel(models.Model):
user = models.ForeignKey(User, db_index=True)
....
In my views, I would do the checking by:
def view(request, id):
model = somemodel.objects.get(id=id, user=request.user)
if model.user = request.user:
...
Would this be the easiest and yet be the correct way to do row level authorisation?
Ideally the views that need to check if the use is authenticated can have the login_required decorator. Then you can use try, except instead of if else because that's more pythonic
#login_required
def view(request, id):
try:
model = somemodel.objects.get(id=id, user=request.user) #this will raise an exception if not found
except Somemodel.DoesnotExist:
return HttpResponseRedirect('/login')
This of course begins to look boiler plate like. That's where Class Based Views come into the picture. Alternatively you can reduce the boiler plate code with
#login_required
def view(request, id):
my_object = get_object_or_404(SomeModel, pk=1, user=request.user)
# get_object_or_404 also throws a MultipleObjectsReturned exception
# when more then one object is returned, so catch it if needed.
You can even reduce one line of checking if model.user = request.user: as you already filtered the data with the logged in user in model = somemodel.objects.get(id=id, user=request.user)
class getUserData(APIView):
def get(self, request, format=None):
userName = request.data['userName']
try:
checkUserLoggedIn = YourAuthenticationModel.objects.get(id=id, user=userName)
getRow = someModel.objects.filter(user=userName)
except ObjectDoesNotExist:
print "User does not exist or logged In"

login_required django decorator

I wanted to use login_required with function based views.I gone through Django's official docs of django.contrib.auth.decorators.login_required. I could not grab it clearly.
Issue is , the control is returning back to login function even though user is already authenticated instead of going to home page.
What else changes are required to allow login using my code?
def login(request):
"""
"""
data_dict = {}
if request.POST:
req_dict = dict(zip(request.POST.keys(), request.POST.values()))
accmgr = AccountManager()
user = accmgr.validate_user(**req_dict)
if user:
ret = redirect('homepage')
else:
data_dict["msg"] = "Username or password is incorrect!"
ret = render(request, "login.html", data_dict)
else:
ret = render(request, "login.html", data_dict)
return ret
#login_required(login_url='/login')
def homepage(request):
'''
'''
return render(request, "adminpage.html", {"title":"Hello World"})
NOTE : accmgr.validate_user internally checks user.is_authenticated.There are some other checks I had to do to allow user so added custom function.
Also added LOGIN_URL in settings.py
LOGIN_URL ='/login/'
login_required decorator checks if request.user.is_authenticated() returns True. Probably the issue is, accmgr.validate_user method does not really authenticate the user.
You should call authenticate() instead, to actually log user in.
from django.contrib.auth import login as django_login
from django.contrib.auth import authenticate
def login(request):
...
req_dict = request.POST.copy()
user = authenticate(
username=req_dict['username'], password=req_dict['password'])
if user:
django_login(request, user)
...
Please see documentation for more information.

Django #login_required decorator

When writing views, it's obviously a good practice - if not mandatory - to use the #login_required decorator.
BUT - that only checks for authenticates users of
from django.contrib.auth.models import User
What I want to accomplish is to also check that the User exists as a UserProfile.
In my app, for instance, I have some UserProfiles. All have User objects related to them, ofcourse.
but I also have other users which don't have a UserProfile. Such user is my admin user.
I want to make sure that requests come from users who have UserProfiles (and that are authenticated).
Is there a way to change the decorator to support that?
Currently I just wrote my own code to do that:
def user_login(request):
context = context = RequestContext(request)
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
try:
user = authenticate(username=username, password=password)
user_profile = user.userprofile
except (ObjectDoesNotExist,AttributeError) as e:
# username and password only prompted for debug purposes.
error_msg = "Invalid login details: {0}, {1}".format(username, password)
print (error_msg)
# print (request)
# return HttpResponse("Invalid login details supplied.")
return render(request, 'bz/login.html', {'error_msg': error_msg})
if user and user_profile:
if user.is_active:
login(request,user)
# return HttpResponse("You're now logged in as " + username)
# return render(request, 'bz/index.html', {})
return render(request, 'bz/index.html', {'userprofile': user_profile})
# return HttpResponseRedirect('bz/login.html')
else:
error_msg = "Your account is disabled"
print (error_msg)
return render(request, 'bz/login.html', {'error_msg': error_msg})
# return HttpResponse(error_msg)
else:
error_msg = "Invalid login details: {0}, {1}".format(username, password)
print (error_msg)
return render(request, 'bz/login.html', {'error_msg': error_msg})
# return HttpResponse("Invalid login details supplied.")
else:
if request.user.is_authenticated():
return render(request, 'bz/index.html', {})
else:
return render(request, 'bz/login.html', {})
Your input would be very much appreciated.
Thank you.
You can use the user_passes_test decorator to take a function that checks the user profile
e.g.
def has_user_profile(user):
#return a True if one exists, else False
#login_required
#user_passes_test(has_user_profile)
def my_view(request):
...

Categories

Resources