Create public profiles for users in django - python

I created a profile view for users and I want everyone to be able to see it without having to log in
But when I click on the profile while not having logged in, it automatically logs into the account of the user I clicked on!
How can I fix it?
This is the view
def public_profile(request, username):
user =
User.objects.get(username=username)
return render(request, 'users/public_profile.html', {"user": user})
This is the url
path('<str:username>/profile/', public_profile, name='public-profile'),

It likely does not log in. But some context processors will add certain elements to the context. For example the django.contrib.auth.context_processors.auth.auth context processor will add a value for the 'user' key to the context if the user is logged in. A template that thus works with {{ user }}, might assume this is the logged in user.
You therefore better pass the user you want to show under a different name, for example profile:
from django.shortcuts import get_object_or_404
def public_profile(request, username):
user = get_object_or_404(User, username=username)
return render(request, 'users/public_profile.html', {'profile' : user})

As Willem Van Onsem says, the user variable is used by the Authentication middleware to represent the current logged user, so your user object is replaced with that. Try changing the name of the variable you use.

Related

DJango user not logging out

I'm new to DJango and I'm trying to make a user auth. My login is working fine but my user isn't logging out.
My Logout view is:
from django.contrib.auth import logout
from django.contrib.auth.models import User
class LogoutView(generic.View):
#staticmethod
def get(request):
if User.is_authenticated:
# Debug statement
print('if')
logout(request)
return redirect('login')
else:
return redirect('index')
My url is working fine because when i go to /logout/, My debug statement executes
but if User.is_authenticated: always returns an object(true).
How can I resolve this issue. Thanks
User.is_authenticated is not what you should do. User is class, show it will have objects which is shown on your request which is already there, and it has nothing to do with the user who is serfing. While, request is the object of the user which carry many things one of them is user.
It should be:
request.user.is_authenticated:

Is it possible to forge HttpRequest attributes for a Django server

I am writing a web app using Django. I am trying to allow a user to see its profile and only his own.
if(not request.user.id == request.GET.get('user_id', '')):
raise PermissionDenied
My question is: is it safe to check this way or is it possible for a smart kid to somehow alter the value in request.user.id to match the user_id of anyone?
The user must be logged in before accessing this page using this:
user = LDAPBackend().authenticate(username=username, password=password)
if(user is not None):
login(request, user)
Yes it should be safe.
request.user get's only populated when authentication with session cookies. Unless and until someone steals the cookie or token it should be no issue.
One thing i don't understand is why do you need user_id parameter here to be explicitly passed.
if you are putting logged in compulsory to view the page. there are two way i can see this.
/profile
Directly get user profile corresponding to the request.user
/<username>
Query the profile corresponding to the username and compare it with request.user.id
request.user is set using AuthenticationMiddleware for each request:
Adds the user attribute, representing the currently-logged-in user, to every incoming HttpRequest object.
If a user is not logged in then request.user is set to Anonymous User. Have a look at Authentication in Web requests.
So, I am not sure how would a smart kid alter the id of the logged-in user.
Mostly, there is a one-to-one relation between the user and its profile. If that's the case you can modify the queryset to get the profile for request.user directly.
request.user is already an object about the current user who send the request to get the page. You can use login_required or to only allow user login to access (2 solutions : decorator or Mixin).
And then you can use your condition to load the page in the function. Example:
=> url.py:
url(r'^profile/$', login_required(app.views.profile), name='profile'),
=> views.py :
def profile(request):
try:
myProfile = User.objects.get(username=request.user.username)
except ObjectDoesNotExist:
return render(request, "error.html", {'message' : 'No Profile Found'})
return render(request, "app/profile.html",
{'myProfile': myProfile})
Like this you can only display YOUR profile (user who send the request) AND you need to be logged.
EDIT: if you don't want "try and catch" you can use get_object_or_404(User, username=request.user.username)

When to redirect when to render

​My scenario:
​My app, handles signup at /profile/signup/ using SingupView(FormView).
class SignupView(FormView):
template_name = "profile/signup.html"
template_name_signup_confirmed = "profile/created.html"
template_name_inactive = "profile/inactive.html"
def form_valid(self, form):
# Create and save inactive user
self.created_user = self.create_user(form, commit=False)
self.created_user.is_active = False
self.created_user.save()
# Create and save user's profile
profile = self.create_profile(form)
# Send registration email
self.send_registration_email([self.created_user.email], registration_code=profile.registration_code)
# Response
return render_to_response(self.template_name_signup_confirmed, {'email': self.created_user.email})
def form_invalid(self, form):
if 'email' in form.errors and form.errors['email'].as_text() == \
'* An inactive user is registered with this email address.':
return render_to_response(self.template_name_inactive, {'email': form.data["email"]})
return render_to_response(self.template_name, self.get_context_data(form=form))
In SingupView().form_valid(form) the User and his Profile are created, user is signed up, but inactive.
After that, in my case there is not success url to redirect, but render a new page, at the same address (/profile/signup/) with a new html saying "An email was sent at youremail#email.com, check and activate".
The same case when an inactive, registered user, tries to signup again, he will get a new page, rendered at the same adress /profile/signup/ saying 'Your email youremail#email.com is already in our db but is not active.. .'
My questions:
Can anyone explains if this is a good way to go, or I need to redirect to new urls, controlled by a new views?
Is there any security risk by using render instead of redirect? Especially on user sign in/sign up?
What is the difference when using redirect or render a new template at the same address? What is the best practice in Django?
Is it ok, to display user's email, in the signup confirmation page and also in the alert page that says that user is registered but inactive in db?
The common pattern for this sort of behaviour is to use a redirect.
I would personally prefer that as it avoid the confuson of one view doing two things - one view displays and processes the form, the other displays a success message.
If the user manages to POST the form data a second time, what do you do?
https://en.wikipedia.org/wiki/Post/Redirect/Get
I am not aware of any greater security risk from using render rather than redirect (though someone with more expertise may know more than me about that).

Using Account Auth to verify if logged in yet

I have a small view:
def AccountHome(request):
return render(request, 'myapp/account/accounthome.html', {
})
In previous views, I've used:
if user is not None and user.is_active
to check if a user is already authenticated or not when using native form classes like: AuthenticationForm for example when logging in a user.
But on this view I am not using that, is there someway to validate whether a user is logged in or not without using this AuthenticationForm classagain? Thisviews purpose is to show the homescreen when logged in, so it seems non-intuitive to extend thatAuthenticationForm` class again.
Any help or thoughts?
Thanks
Use is_authenticated() method
Like this: if request.user.is_authenticated():
You can find the reference here: https://docs.djangoproject.com/en/dev/ref/contrib/auth/#methods

Django- why inbuilt auth login function not passing info about user to after successful login url

Hi I used the django inbult auth urls and views for my project and now have finished the initial user account creation/login/reset password process.
Now, the user can log in and be redirected to the after successful login url accounts/profile/.
I have several doubts on the django login function. For convenience, I've copy paste the django inbuilt login function code below.
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
"""
Displays the login form and handles the login action.
"""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(request, data=request.POST)
if form.is_valid():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
current_site = get_current_site(request)
context = {
'form': form,
redirect_field_name: redirect_to,
'site': current_site,
'site_name': current_site.name,
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
My questions are:
1 Is the REDIRECT_FIELD_NAME in the function set as '/profile/' in django.contrib.auth ?
I could see this variable is imported from django.contrib.auth
from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login, logout as auth_logout, get_user_model
I don't have any setting for this variable, but after user successfully logged in, the page will be directed to /accounts/profile/
2 Has the login function passed the account info about the user? If yes, how can I access it?
From the code, if user successfully logged in, page will be redirected: return HttpResponseRedirect(redirect_to)
in my case, redirected to accounts/profile/ , initially the view for the url was simply a
HttpResponse("You have logged in successfully")
now when I am trying to implement the view function, I realize that no info about the user has been passed.
I've tried to print request in the view function, but there is no info about the user in the message printed in the server terminal, all I get is a long list of system settings or other info. However, the login should pass the info of who has just successfully logged in to the successful log in urls right?
Thank you very much for explaining.
After the login, you can access the user info by referring request.user in views and just {{user}} in templates. All you need to make sure is you're passing the RequestContext in the HttpResponse for the future request.
Yes, REDIRECT_FIELD_NAME is defined in __init__.py of django.contrib.auth which is simply a "next" what you passed from the login form.
In Django, there are more than one ways to force a user to login. By decorating a view function with #login_required, by calling the build-in login view for an user defined URL and etc., Refer about the login settings variables here. You'll get some more ideas.
Building custom login page. That link gives you an example for custom login implementaion. Consider you have decorated a view with #login_required and it's corresponding URL is /login_test/. Then the {{next}} context variable in the login form will be rendered with /login_test/. So after you login,
<input type="hidden" name="next" value="{{ next }}" />
This element's value will be taken for redirecting as per the REDIRECT_FIELD_NAME. Though I suspect that that example is missing the setting of settings.LOGIN_URL to the URL login/. Never mind, it's being passed as an argument in the decorator itself.
To override this behavior just put following in settings.py of your app :
LOGIN_REDIRECT_URL = "/"
This will redirect to your home page. You can change this url to preferred url.
Once the user is redirected to accounts/profile/ the view for that link will be returned. You can access information about the currently logged in user there as per this post by using request.user. Also tip to see what information you have access to in your views. Use import pbd; pdb.set_trace(). This pops you into a python prompt with access to all of the current variables. To see all the defined variables call locals(), though this will print out a ton of junk along with it. In the template you can display a "you can't access this page" message if the user isn't logged in.

Categories