I have created a simple app for file upload. Everything worked fine.Then I wanted to add simple login and now I have problems.
These are my views
def login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(username=cd['username'],password=cd['password'])
if user is not None:
if user is active:
login(request,user)
return HttpResponse('Authenticated successfully')
else:
return HttpResponse('Disabled account')
else:
return HttpResponse('Invalid login')
else:
form=LoginForm()
return render(request,'account/login.html',{'form': form})
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('list'))
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render(request,'list.html',{'documents': documents, 'form': form})
This is fileupload/urls
from django.conf.urls import url
from fileupload.views import list
from fileupload.views import login
urlpatterns = [
url(r'^list/$', list, name='list'),
url(r'^login/$', login, name='login'),
]
My forms
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
class DocumentForm(forms.Form):
docfile = forms.FileField(label='Select a file')
When I go to
http://127.0.0.1:8000/fileupload/list/
everything works fine.
If I try
http://127.0.0.1:8000/login/
I got this
I am confused becuase template is getting data from one fun and not from the other.
How to debug this?
It's clear that you and list and login in the URL should go after http://127.0.0.1:8000/fileupload/
Try check http://127.0.0.1:8000/fileupload/login/
Read this docs https://docs.djangoproject.com/en/1.11/topics/http/urls/
Related
I am building an app that allows users to view posts. However, every time I try to log in if I do not set the LoginRequiredMixin the user will still be able to view posts after logging out. But when I set the LoginRequiredMixin everytime user puts info it keeps going back to main page and nothing happens.
my home/views.py
#login_required
def home(request):
posts = Post.objects.all()
context = {'posts':posts}
return render(request, 'home/home.html', context)
class PostListView(ListView):
model = Post
template_name = 'home/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-date_posted']
my home/urls.py:
path('',views.PostListView.as_view(), name='home'),
my main/urls.py
urlpatterns=[
path('signup/',views.signup,name='signup'),
path('signin/',views.user_login, name='user_login'),
path('signout/', views.user_logout, name='user_logout'),
path('',views.main_page,name='main_page'),
path('edit/', views.edit_profile, name='edit_profile'),
path('', include('django.contrib.auth.urls')),
]
my main/views.py:
def main_page(request):
return render(request,'main/user_login.html')
#login_required
def user_logout(request):
logout(request)
return redirect('main:main_page')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
return redirect('main:main_page')
else:
form = SignUpForm()
return render(request, 'main/signup.html', {'form': form})
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = authenticate(request, username=username, password=password)
if user is not None:
return redirect(reverse('home:home'))
else:
messages.error(request,'Sorry, the username or password you entered is not valid please try again.')
return HttpResponseRedirect('/')
else:
form=AuthenticationForm()
return render(request, 'main/user_login.html', {"form":form})
int my settings.py I only have:
LOGIN_URL = 'main:main_page'
I have been working a lot on this and I cannot find how to fix this issue.
Thanks in advance!
I guess the authentication is failing. However here is some snippet you can try.
from django.shortcuts import render,redirect
from django.contrib.auth import login,logout
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.decorators import login_required
def loginView(request):
if request.method == 'POST':
# Authentication form is provided by django, it will parse username and password
# in the post request
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return redirect('home:home')
else:
form = AuthenticationForm()
return render(request, 'main/user_login.html', context={'form': form})
#login_required
def logout_request(request):
logout(request)
return redirect('home:user_login')
In settings.py make sure you have following properties set:
LOGIN_URL = reverse_lazy('home:user_login')
LOGIN_REDIRECT_URL = reverse_lazy('home:home')
LOGOUT_REDIRECT_URL = reverse_lazy('home:user_login')
Note: If you are using custom made user(other than default user model provided by djnago) then make sure you have following property in settings.py set, otherwise AuthenticationForm won't work.
AUTH_USER_MODEL = 'AppName.YourCustomUserModel'
I am following a Django tutorial where the blog app and users app are separate. Upon registering as a user I would like the user to be redirected to a view in the blog app. Here is the users app views.py:
def register(request):
if request.method == 'POST': # if form was submitted w data
form = UserCreationForm(request.POST) #instantiate form w post data
if form.is_valid():
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}')
return redirect('blog-home') #not working
else:
form = UserCreationForm()
return render(request, 'users/register.html', {'form':form})
and here is the blog app's views.py:
from django.shortcuts import render
from django.http import HttpResponse
from .models import Post
# Create your views here.
def home(request):
posts = Post.objects.all()
return render(request, 'blog/home.html', {'posts':posts})
and the url pattern tied to said view:
path('', views.home, name = 'blog-home'),
When a user submits the form, I get the following error: Reverse for 'home' not found. 'home' is not a valid view function or pattern name.
I am not sure why this is, I believe I copied the code word for word and the example in the video is working.
In your app's urls.py mention app_name so that you can redirect to any app's views.
blog/urls.py
app_name = 'blog'
urlpatterns =[...
]
Now you can redirect to the blog app home view like this
return redirect ('blog:blog_home')
#return redirect ('app_name:url_name')
If you want to redirect to url named 'blog-home' you need to reverse('blog-home').
Your url isn't called 'home' but 'blog-home'. Your error mention that you tried to reverse for 'home'.
It should work if you change your view:
def register(request):
if request.method == 'POST': # if form was submitted w data
form = UserCreationForm(request.POST) #instantiate form w post data
if form.is_valid():
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}')
return redirect(reverse('blog-home'))
else:
form = UserCreationForm()
return render(request, 'users/register.html', {'form':form})
The login function is not working , after i call login , authenticated is set 'true' but after i redirect to 'main' view authenticated is set 'false'. How to keep the user logged in even after redirection?
class LoginForm(forms.Form):
user = forms.CharField()
password = forms.CharField()
def login(self):
try:
cred = users.objects.get(username = user)
if password==cred.password):
return (True, cred)
return (False, 'Invalid Password.')
except:
return (False, 'Not exist')
from django.contrib.auth import login as auth_login
def login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
valid, message = form.login()
if valid:
auth_login(request, message)
print(request.user.is_authenticated)
# this is not working
return redirect(main)
else:
return redirect(login)
form = LoginForm()
args = {'form': form}
return render(request, 'accounts/login.html', args)
def main(request):
print(request.user.is_authenticated)
You shouldn't write check your user credentials in form class. Do it in your login view. Example:
# views.py
from django.contrib.auth import authenticate, login
from django.urls import reverse
from django.shortcuts import redirect, render
def login_view(request): #changed_the name shouldn't be login
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
user = authenticate(username, password)
if user:
login(user)
return redirect(reverse("main"))
else:
return redirect(reverse("login"))
form = LoginForm()
args = {"form": form}
return render(request, 'accounts/login.html', args)
# urls.py
urlpatterns = [
path("login/", views.login_view, name="login"), # <-- really important
path("main/", views.main_view, name="main")
]
To summarize - to redirect to another page use redirect function. If you set name parameter in url of you view, you can reffer to this view using reverse. Also don't reinvent the wheel and write your own authentication function. Django provides: authenticate(username, password) and login(user) function.
I have already used login class
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
And views file of my app
from .forms import LoginForm
def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(username=cd['username'],password=cd['password'])
if user.is_active:
login(request, user)
return HttpResponse('Authenticated!')
else:
return HttpResponse('Disabled account')
else:
form = LoginForm()
return render(request, 'account/login.html', {'form': form})
(hunter) provides email verifier.This is HTTP request example
GET https://api.hunter.io/v2/email-verifier?email=steli#close.io
How to modify my login and views files?
Try to use the code below :
import urllib2
get_request = urllib2.urlopen('https://api.hunter.io/v2/email-verifier?email=' + username)
then the get_request variable will contain a JSON object as mentioned in hunter documentation.
the get_request will be added in after the cd = form.cleaned_data
I've this:
def profile(request, username):
if request.method == 'POST':
if request.user.is_authenticated():
new_message = Message(author = request.user)
form = MessagesForm(request.POST, instance = new_message)
else:
form = MessagesForm(request.POST)
if form.is_valid():
form.save()
else:
to_user = User.objects.get(username = username)
form = MessagesForm(initial = {'user': to_user.pk})
return render(request, "profile.html", {
'username': username,
'form': form,
'messages': messages,
})
This form submit a message and return the same page. My problem is that after the submit I see again my field filled with my information. How to clear it after the submit?
After saving form instead of showing post dict assign the empty form
form = EmployeeForm()
if request.method == "POST":
pDict = request.POST.copy()
form = EmployeeForm(pDict) #if not valid shows error with previous post values in corresponding field
if form.is_valid():
form.save()
form = EmployeeForm() # show empty form no need to give HttpResponseRedirect()
It's standard to redirect after form submission to prevent duplicates.
Just return a redirect to your form on success.
if form.is_valid():
form.save()
return http.HttpResponseRedirect('')
after save() you can return 'form' key with MessagesForm(request.GET) value.
return render(request, "profile.html", {
'username': username,
'form': MessagesForm(request.GET),
'messages': messages,
})
Usually you can initialize the same empty form after you have saved datas:
if request.method == "POST":
rf = RegistrationForm(request.POST)
if rf.is_valid():
print 'Saving datas..'
#logic to save datas
rf = PreRegistrationForm()
return render_to_response('registration/confirmation_required.html', {'settings': settings}, context_instance=RequestContext(request))
Try using HttpResponseRedirect('/') instead of HttpResponseRedirect('') in #Karthikkumar's answer, especially if your home view is an empty path, for instance you have in your urls.py file:
urlpatterns = [path('',views.home_view),]
I had similar issues as those discussed above where HttpResponseRedirect('') directed me to a blank page. Let me know if adding the slash works for you!
You can use this:
Sometimes you can use this idea take attrs={ "autocomplete":"off"} for each inputs.
You can redirect back to the initial post
post_url = request.build_absolute_uri(post.get_absolute_url())
return HttpResponseRedirect(post_url)
please note that 'post' is an instance of the model created
I am hoping you have already defined a logic for GET methods. In the case that you have, all you can do is simply add return request.META['HTTP_REFERER'] at the end.
See what I mean:
def profile(request, username):
if request.method == 'POST':
if request.user.is_authenticated():
new_message = Message(author = request.user)
form = MessagesForm(request.POST, instance = new_message)
else:
form = MessagesForm(request.POST)
if form.is_valid():
form.save()
else:
to_user = User.objects.get(username = username)
form = MessagesForm(initial = {'user': to_user.pk})
return HttpResponseRedirect(request.META['HTTP_REFERER'])
This should work, I just tested it.
**Maybe I am late but for Django 4.x developers can use: **
from .forms import TodoForm
from django.contrib import messages
from django.http import HttpResponseRedirect
def mytodos(request):
form = TodoForm()
if request.method =='POST':
form=TodoForm(request.POST)
if form.is_valid:
form.save()
messages.success(request,'Task saved successfully')
return HttpResponseRedirect('/todo/')
mycontext={'form':form}
return render(request, 'todo/todo.html',mycontext)
in my urls.py: , i have set path('todo/',views.mytodo, name='todolist')
As you can see, after saving form, mycode will redirect to /todo/ which is automatically refreshed after every submit and a fresh form comes again everytime. If you are a good django dev, you will understand what I did. Make sure to reply if you have any queries .Thanks :)
When we reload the page (F5 or ctrl+shift+R), it submits the previously sent data. so instead of refreshing, we will directly hit the url using return HttpResponseRedirect('/posts/')
This way it will show the page with empty form (now even if you refresh it will only show data, won't submit it previous data again)
from django.shortcuts import render, HttpResponseRedirect
from django.views import View
from .models import Post
from .forms import PostForm
class PostListView(View):
def post(self, request, *args, **kwargs):
posts = Post.objects.filter(author=request.user).order_by('-created_on')
form = PostForm(request.POST)
if form.is_valid():
new_post = form.save(commit=False)
new_post.author = request.user
new_post.save()
return HttpResponseRedirect('/posts/')
context = {
'post_list': posts,
'form': form
}
return render(request, 'social/post_list.html', context)