HttpResponseRedirect not working Django 1.7 - django

I am having a problem with HttpResponseRedirect in Django. It seems that, whatever parameters I try, it either throws an error, or it redirects without changing the URL. I am using it on a custom login_user view, and I want the URL in the address bar to change after they are redirected. If I use redirect instead of HttpResponseRedirect, it does not change. Either way, I can get it to serve the correct template, but the URL stays the same. Being new to Django, it would be helpful if someone could explain to me how to do this and why my current code is not working.
I have seen a couple of similar questions to mine on Stack Exchange, but the answers have not helped.
Here are the relevant parts of my views.py (please note the indenting has gone weird due to copying and pasting in here, and is not the cause of the error).
from django.http import *
from django.contrib.auth import authenticate, login, logout
def login_user(request):
logout(request)
username = password = ''
if request.POST:
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('dashboard')
else:
state = "Your account is not active, please contact the app administrator."
else:
state = "Your username and/or password were incorrect."
state = "Please log in below..."
context = RequestContext(request, {
'state': state,
'username': username,
})
return render_to_response('bank/auth.html', {}, context)
dashboard is the name of another view, and it works fine in a redirect from my index view. I've also tried hard-coding the url in, but that doesn't work either. Any suggestions?? Thanks.

If you use HttpResponseRedirect, you must provide the url, not the name of the url.
You can either get the url by using reverse:
from django.core.urlresolvers import reverse
def my_view(request):
...
return HttpResponseRedirect(reverse('dashboard'))
or by using the redirect shortcut.
from django.shortcuts import redirect
def my_view(request):
...
return redirect('dashboard')
If using the either of the above approaches does not work, then there's probably a mistake somewhere else in the view. It's difficult to tell where, since the indentation is incorrect. Try adding some logging or print statements to see if you are really returning the redirect where you think you are.

In this particular case, the problem wasn't anything to do with my view code, it was actually a problem caused through using JQuery mobile. I found the answer here: Error with Redirects in JQuery Mobile which was to set the data-url attribute on the page div.
However, I have up-voted Alasdair's answer, as his way is the correct one of the ways I had tried.

I personally prefer the simple way as follows:
In urls.py:
url(r'^dashboard/$', 'appname.views.dashboard_view', name='dashboard_view'),
In views.py:
from django.http import HttpResponseRedirect
def dashboard_view(request):
...
return HttpResponseRedirect('/dashboard/')

Related

How to set LOGIN_URL variable in Django settings so it doesn't redirect anywhere while not logged in

When trying to access url get_room_messages if user is not logged in #login_required redirects him to: /accounts/login/?next=/get_room_messages
(as specified in docs)
I want it to do nothing (or redirect to the original url, in this example /get_room_messages). I don't want to hardcode it like #login_required(login_url='/get_room_messages'), ideal solution would be to get somehow original url and pass it into #login_required() decorator.
#login_required()
def get_room_messages(request):
user_id = request.user.user_ID
user = get_object_or_404(CustomUser, pk=user_id)
Thank you for help!

Django dynamic url in root domain overwrites all other urls

I want to have a dynamic root url for different users. All users get their own url. I want to have the dynamic url in the root but also be able to have more hardcoded urls as alternatives, for example on the url that the user will edit their profile.
The problem i have is that all urls redirect to view2 and none goes to view1.
path(r'edit/<str:user>/', views.view1, name='view1'),
path(r'<str:user>/', views.view2, name='view2'),
example.com/edit/user always gets redirected to example.com/user which is not wanted.
views:
def viewID(request):
return render(request, 'viewID.html')
This worked for me:
urls.py:
path('edit/<str:user>/', views.view1, name='view1'),
path('<str:user>/', views.view2, name='view2'),
views.py:
from django.http import HttpResponse
def view1(request, user):
return HttpResponse('This is view1: ' + user)
def view2(request, user):
return HttpResponse('This is view2: ' + user)
So the problem was quite frustrating. I needed to clear the cache or run in a private window since django kept appending a "/" to example.com/user/ which of course would go to view1 since it exects a key

Django Auth Additional Validation

I need compare a boolean variable when I do login (variable name: approved)
If variable is true:
login success; 7
else
login error;
I have variable stored in database.
My form:
class LoginForm(AuthenticationForm):
username (...)
password (...)
Urls:
`url(r'^login/$', auth_views.login, {'authentication_form': LoginForm},` `name='login'),`
Views:
def login(request):
return render(request, 'registration/login.html')
How to change default login to allow this?
Limit access based on certain permissions
There's a really nice way to check if some "test" is passed. In your example, a "test" would be if approved variable is True. You can do something like this:
from django.contrib.auth.decorators import user_passes_test
def check_approved():
# get the approved variable from database
approved = True # or false, depends on what you read from the database
return approved
#user_passes_test(check_approved)
def login(request):
...
So, #user_passes_test() decorator receives a callback which must return True or False. You can read more about it in the docs.
If this doesn't help you, please elaborate a bit more on what you would like to do exactly and why this method can't help you.

Doing User Profiles In Django

I'm trying to set up user profiles in my site so we have:
www.example.com/someuser
www.example.com/anotheruser2
in my urls.py
url(r'^(?P<profile>[0-9A-Fa-f]{1,36})/', 'site.views.profile),
and my view:
def profile(request, profile):
... do something ...
There are two questions:
Is this the correct way to do this or is there a better way?
How should I handle other urls, like "aboutus", etc.
For Point 2, I would do:
url(r'^aboutus/', 'site.views.aboutus'),
url(r'^(?P<profile>[0-9A-Fa-f]{1,36})/', 'site.views.profile),
So now profile will be the catchall for everything else in the site, and I have to check for a valid profile then throw a 404 if a password is not found.
Again, is there a better way to do this?
It's not a good idea to use site.views.profile as a catchall. It's not good separation of responsibilities, it shouldn't be its job. How about something like this instead:
url(r'^profile/$', 'site.views.profile_self'),
url(r'^profile/(?P<profile_name>[0-9A-Fa-f]{1,36})/$', 'site.views.profile'),
url(r'^aboutus/', 'site.views.aboutus'),
For the catchall, use a custom 404 page, or you could let the server raise a 404 error.
accounts/models.py
from django.db import models
class User():
def get_profile(self):
return UserProfile.objects.get_or_create(user_id=self.id)
class UserProfile(models.Model):
user = models.OneToOneField(User)
# another fields
accounts/urls.py
url(r'^profile/$', 'site.views.profile'),
accounts/views.py
from django.contrib.auth.decorators import login_required
#login_required
def profile(request):
# get current logged user profile
profile = request.user.get_profile()
this way the user logged only can see his own profile.
and for the point 2, what's wrong with this?
url(r'^about_us/$', 'site.views.about_us'),
--UPDATE--
ah, ok. then, you are right. but why not with the username?
accounts/urls.py
url(r'^(?P<username>[-\w]+)/$', 'site.views.profile'),

no user matches the given query while using username as an argument

Till now i have been using userid's (pk) as an argument in the profile urls for my application. Recently i decided to use the username instead of the user id's So i changed the following :
Urls.py
# This was what i was using previously
url(r'^profile/(?P<uid>\d+)/$', 'app.views.user_profile', name="profile"),
# Changed the above to this.
url(r'^profile/(?P<username>[-\w\d]+)/$', 'app.views.user_profile', name="profile"),
Views.py
# Previous view
#login_required
def user_profile(request, uid):
user = get_object_or_404(models.User, pk=uid)
profile = helpers.get_profile(user)
render_to_response('profile.html', {'profile' : profile})
# Changed the above to
#login_required
def user_profile(request, username):
user = get_object_or_404(models.User, username=username)
profile = helpers.get_profile(user)
render_to_response('profile.html', {'profile' : profile})
Until Now it's all good. When i try to visit 127.0.0.1:8000/profile/some_username/ instead of the previous 127.0.0.1:8000/profile/some_number/ it works fine.
I have a toolbar in the profile.html, which contains links such as:
/profile/edit/
/profile/settings/
in the urls.py these urls map to very simple views. Such as the following.
#login_required
def profile_settings(request):
"""
This view helpers.renders the profile's settings panel
"""
print 'hello'
rec, can = helpers.get_user_or_noprofile(request.user)
if not can is None:
gform = forms.CandidateGeneralSettingsForm(instance=can)
jsform = forms.CandidateJobSearchSettingsForm(instance=can)
data = {'candidate' : can, 'gform' : gform, 'jsform' : jsform }
else:
form = forms.RecruiterSettingsForm(instance=rec)
data = { 'recruiter' : rec, 'form' : form }
return helpers.render(request, 'profile_settings.html', data)
The weird part is after i changed to use username in the profile url. As soon as i click on any of the links in the toolbar, i see the 404 : Error : No User matches the given query. page.
To debug i tried printing a few debug statements within these views and found out something more weird. Nothing gets printed even if i Comment the whole code inside the view and just write a print statement.
This makes me doubt that the problem might be with the login_required decorator. but if that's the case howcome it is working while visitng 127.0.0.1:8000/profile/some_username/.
I really can't think of anything that might be causing this. Any help will be greatly appreciated. Thanks.
PS: Also, JFYI, i am using a custom Email Authentication backend that lets user login through their email address instead of the username.
It doesn't work because edit is not a valid username.
This url /profile/edit/ matches ^profile/(?P<username>[-\w\d]+)/$, and username becomes edit.
Since you don't have a user called "edit", this user = get_object_or_404(models.User, username=username) fails, and raises a 404.
The same for /profile/settings/.