redirect() between views in separate apps - django

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})

Related

In django whenever I try to run the server, I want to see the login page first, but I am seeing the index page

I am attaching my code in views and urls.py. Whenever the server runs, I want to see the login page first, but I am seeing an error that this page is not working.
#views.py
def loginPage(request):
if request.user.is_authenticated:
return redirect('/')
else:
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:
login(request, user)
return redirect('/')
else:
messages.info(request, 'Username OR password is incorrect')
context = {}
return render(request, 'accounts/login.html', context)
# urls.py
urlpatterns = [
path('', views.loginPage, name="login"),
path('index/',views.index,name="index"),
You should pass #login_required decorator in your view. If you don't want to pass this decorator in your every view there are second way which you can do using middleware. In middleware you check the user is authenticated or not. If yes it redirects user to index page other way to login page. Here is an example:
Create middleware.py file and write this code inside it:
from django.utils.deprecation import MiddlewareMixin
from django.urls import reverse
from django.shortcuts import redirect
class LoginCheckMiddleWare(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
modulename = view_func.__module__
user = request.user # Who is the current user ?
if user.is_authenticated:
return redirect(reverse('index-page'))
else:
if request.path == reverse('login_page') or modulename == 'django.contrib.auth.views':
pass
else:
return redirect(reverse('login_page'))
After that add this line inside MIDDLEWARE in settings.py file:
'folder.middleware.LoginCheckMiddleWare', instead of folder write your middleware file located folder

Can we use instance in the form?

hello guys i am working on form i didint find how to get instance in the form. This is not a model form
def form(request):
if request.method == 'POST':
form = Form(request.POST)
if form.is_valid():
else:
form = Form()
return render(request, 'app/form.html', {'form': form})
You should have a form class something like below:
forms.py
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
Now To handle the form we need to instantiate it in the view for the URL where we want it to be published:
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import NameForm
def get_name(request):
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
# process the data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
Refer the Django documentation for more details.
https://docs.djangoproject.com/en/3.0/topics/forms/

Django LoginRequiredMixedIn doesnn't let users sign in

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'

Django.contrib.auth.login is not working after i redirect to a different url

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.

Why is my template not getting view data from one func?

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/