I'm working on a blog build on django and doing the comment stuff and I would like to build it from scratch here my views function:
def topic_detail(request, slug):
topic = get_object_or_404(Topic, slug=slug)
form = CommentForm()
if request.method == 'POST':
if request.user.is_authenticated:
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.topic = topic
comment.created_by = request.user
comment.save()
return redirect('board:topic_detail', slug=topic.slug)
else:
redirect('accounts:login')
else:
form = CommentForm()
return render(request, 'topic.html', {'topic':topic, 'form':form})
my page layout would be:
< ............................>
Something I want to write
<.............................>
Comment Field
<.............................>
Comments
So when user presses the button, server will check if that user is authenticated. If yes comment is updated, If no user will be directed to login views. Here the problem, when I'm logged in everything works fine, but when I log out test the views, It does not redirect me to the login views but just reload the page. I would appreciate if you help me.
Thanks!
You should use return redirect(....) instead of just redirect(...) to return the actual HttpResponse. Now your code continues to the last line and renders the same page again.
Related
Look I have a problem with displaying photos after updating.
I have a function from my views.py
def addHW(request):
if request.user.is_authenticated:
obj = Profile.objects.get(user=request.user.id)
else:
obj = ''
profile = request.user.profile
form = CustomerForm(instance=profile)
template = 'HW/add.html'
context = {'form': form, 'profile': obj}
if request.method == 'POST':
form = CustomerForm(request.POST, request.FILES, instance=profile)
if form.is_valid():
Profile.objects.get(user=request.user.id).photo.delete()
form.save()
return render(request, template, context)
and after deleting previous photo and saving of new photo, page must be reloaded. And page shows visual reloading, but HTML shows src of previous image. And after manual refreshing page displays new src of photo.
How i can resolve it?
In case of a successful post, you need to make a redirect to implement the Post/Redirect/Get pattern. – Willem Van Onsem 32 mins ago
I want to display login_required message like you have to login first to give the review while redirecting to the login page. How can i achieve this.
views.py
#login_required(redirect_field_name='next',login_url='shop:users_signin')
def review(request,slug):
if request.method == "POST":
form = ReviewForm(request.POST)
if form.is_valid():
review = form.save(commit=False)
review.product = Product.objects.get(slug=slug)
review.user = request.user
review.save()
messages.success(request, 'Review Saved.')
return redirect('shop:detail', slug)
else:
return redirect('shop:detail',slug)
#login_required decorator is for convenience but doesn't make it easy to customise the behaviour. If you use CBVs, the LoginRequiredMixin makes it easier, because you can override handle_no_permission() to add a message to the request before the redirect occurs.
So the best alternative you have if you use simple function based views it to write the authentication check yourself:
def review(request, slug):
if not request.user.is_authenticated:
messages.info("You need to be logged in in order to give a review")
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
# rest of your view here
And then in your login template make sure you display the message.
I have a very simple index page view, from which the user can fill in a login popup, which sends a post request to /login
def index(request):
"""Shows list of studyspaces, along with corresponding 'busyness' score"""
context = {'study_space_list': StudySpace.objects.order_by('-avg_rating')}
if request.user.is_authenticated():
context['user'] = request.user
else:
context['login_form'] = LoginForm()
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
If the login is valid it simply redirects to the index page, this works fine.
The login view looks as follows:
def user_login(request):
form = LoginForm(request.POST)
if request.method == 'POST' and form.is_valid():
user = form.login(request)
if user:
login(request, user)
return redirect(reverse('spacefinder:index'))
# Load the context all over again
context = {
'study_space_list': StudySpace.objects.order_by('-avg_rating')
}
context['login_form'] = form
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
However when the login is incorrect I want to be able to refresh the page and show the login form errors inside the index template (in the login popup)
I'm actually able to achieve this with the above code, but I'm unhappy with the solution for the following reasons:
I have to manually fetch the context all over again, e.g user/student forms and studyspaces, this goes against the DRY principle
When the page is refreshed the url is localhost:8000/spacefinder/login
Screenshot of behaviour here
I'm wondering if there's somehow a way to use redirect to reload the index page and somehow pass errors from my login_form, e.g. something like:
return redirect('spacefinder:index', {'login_form': form})
I've looked into using messages to pass form validation errors, but struggled to get this working since Validation Errors are thrown inside forms.py, and I'm unable to fetch the request instance from inside a ModalForm to properly create a message
You are doing it the wrong way around.
Consider these prerequisites:
entry point to your page is the index view
the index view must only be accessible by authenticated users
the login view allows both methods GET and POST and is accessible to anonymous users only
The reason to use Django is to make use of all the features that it offers, and that includes handling of the above (because that is what most pages need, not only you).
To set it up correctly you need to define your urls.py like this:
from django.contrib.auth.decorators import login_required
urlpatterns = [
....
url('^login/$', user_login, 'login'),
url('^/$', login_required(index), 'index'),
....
]
In your settings/base.py (or settings.py if you have no environment differentiation) tell Django how to redirect users:
LOGIN_URL = reverse_lazy('login')
LOGIN_REDIRECT_URL = reverse_lazy('index')
https://docs.djangoproject.com/en/1.9/ref/settings/#login-url
https://docs.djangoproject.com/en/1.9/ref/settings/#login-redirect-url
Simplify your index view:
def index(request):
"""Shows list of studyspaces, along with corresponding 'busyness' score"""
context = {'study_space_list': StudySpace.objects.order_by('-avg_rating')}
if request.user.is_authenticated():
context['user'] = request.user
else:
return HttpResponseForbidden() # prevented by Django, should never happen
return render(request, 'spacefinder/index.html', context)
Let the user_login view deliver the empty login form:
#require_http_methods(["GET", "POST"])
def user_login(request):
params = getattr(request, request.method)
form = LoginForm(params)
if request.method == 'POST' and form.is_valid():
user = form.login(request)
if user:
login(request, user)
return redirect(reverse('spacefinder:index'))
# Load the context for new form or form with errors
context = {
'study_space_list': StudySpace.objects.order_by('-avg_rating')
}
context['login_form'] = form
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
You have not presented any code that handles the UserForm or the StudendForm. You would need to add that to the user_login view, as well - if this is something that all users should fill in every time they login. Otherwise use a different view.
It's worth looking at modules like allauth. They might spare you some work when it comes to allowing users to login with their e-mail addresses, ascertain that e-mail addresses are unique in the system etc.
I have a user sign up and login template set to send information to the same view (detail). They were both working fine before, however now the redirect on user creation is no longer going to the correct URL (http://127.0.0.1:8000/accounts/login/?next=/accounts/21/) the "accounts/login?next=" portion of the URL is being added for some reason and I cannot understand where it came from as it was not there before.
I'm using stronghold which makes every view login_required unless noted otherwise with #public above it.
I have found some posts about LOGIN_URL needs to be set in setting.py or a next key. However this was working fine before so I do not think that is the problem. let me know if you need more code posted and I will put it up.
Thanks,
-the route I want to hit is
url(r'^accounts/(?P<user_id>\d+)/$', views.detail, name='detail')
-my register view is below
#public
def register(request):
if request.method == 'POST':
form = EmailUserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
playthrough = PlayThrough(user_id=new_user.id)
playthrough.save()
request.session['user_id'] = new_user.id
return HttpResponseRedirect('/accounts/{}/'.format(new_user.id))
else:
form = EmailUserCreationForm()
return render(request, 'dep_server/register.html', {
'form': form,
})
-this is he view that is supposed to render the user info
def detail(request, user_id):
if request.session['user_id'] == int(user_id):
user = EmailUser.objects.get(id=user_id)
module_list = ModuleRef.objects.all()
return render(request, 'dep_server/detail.html', {
'user': user,
'module_list': module_list
})
else:
return HttpResponseRedirect('/accounts/auth/')
I figured out the problem, I was not logging in the user on creation. Which is why the login worked and the sign up did not. below is the code that I added to the register view, which got it to work.
user = authenticate(
email = form.cleaned_data['email'],
password = form.cleaned_data['password2']
)
login(request, user)
Struggling with my very basic django auth login system. When a new user registers, they are first redirected to /user/user_id as I'd like (the user is also being created fine), but they are then redirected to /login?next=/user/user_id/ which is being done by the #login_decorator over the user view, (the problem stops if I remove the decorator). (nb. Debug toolbar is breaking up the redirect sequence for me to see). However, if I then manually I include Register view below. I can't see why it is not logging in immediately upon registration. The login method seems to be all there:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
new_user = authenticate(username = request.POST['username'],
password = request.POST['password1'])
login(request, new_user)
context = RequestContext(request)
context['user_id'] = new_user.id`
url = '/user/%s/' % new_user.id
return HttpResponseRedirect(url)
else:
form = UserCreationForm()
return render_to_response("registration/register.html", {'form': form},
context_instance=RequestContext(request))
Can you help? Thanks.