redirect, can't leave login page - django

having trouble with this tutorial. in my views.py I have this function for login, in views.py:
def login_view(request, *args, **kwargs):
form = AuthenticationForm(request, data=request.POST or None)
if form.is_valid():
user_ = form.get_user()
login(request, user_)
**return redirect("/")**
context = {
"form": form,
"btn_label": "Login",
"title": "Login"
}
return render(request, "accounts/auth.html", context)
however when i try to change the redirect , i only get errors, what should I put in the redirect? i've tried everything like
return redirect("/tweets/list.html")
and
return redirect("public/index.html")
both are locations of file names in the templates folder. I am getting the error, "Page not found (404)". The only address that did redirect was when I put https://www.google.com/
in accounts/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
# Create your views here.
# Function based views to Class Based Views
def login_view(request, *args, **kwargs):
form = AuthenticationForm(request, data=request.POST or None)
if form.is_valid():
user_ = form.get_user()
login(request, user_)
return redirect('')
context = {
"form": form,
"btn_label": "Login",
"title": "Login"
}
return render(request, "accounts/auth.html", context)
def logout_view(request, *args, **kwargs):
if request.method == "POST":
logout(request)
return redirect("/login")
context = {
"form": None,
"description": "Are you sure you want to logout?",
"btn_label": "Click to Confirm",
"title": "Logout"
}
return render(request, "accounts/auth.html", context)
def register_view(request, *args, **kwargs):
form = UserCreationForm(request.POST or None)
if form.is_valid():
user = form.save(commit=True)
user.set_password(form.cleaned_data.get("password1"))
# send a confirmation email to verify their account
login(request, user)
return redirect("/")
context = {
"form": form,
"btn_label": "Register",
"title": "Register"
}
return render(request, "accounts/auth.html", context)
here is urls.py:
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, re_path, include # url()
from django.views.generic import TemplateView
from accounts.views import (
login_view,
logout_view,
register_view,
)
from tweets.views import (
home_view,
tweets_list_view,
tweets_detail_view,
)
urlpatterns = [
path('', home_view),
path('admin/', admin.site.urls),
path('global/', tweets_list_view),
path('login/', login_view),
path('logout/', logout_view),
path('register/', register_view),
path('<int:tweet_id>', tweets_detail_view),
re_path(r'profiles?/', include('profiles.urls')),
path('api/tweets/', include('tweets.api.urls')),
re_path(r'api/profiles?/', include('profiles.api.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
thnx

Redirect should take a valid path to an url defined in urls.Py, not a file in templates/some/urls.html.
I would suggest not to used "hard coded urls" though, but instead using the view name and parameters such as return redirect('some-view-name', foo='bar')

i solved the error by looking at urls.py, looking into url patterns, picking
path('global/', tweets_list_view),
and dropping '/global/' into return redirect("/") so that line looks like:
return redirect("/global/")

Related

Django redirect another view from another app form

contact/views.py
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from .forms import ContactForm
def contactView(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
subject = form.cleaned_data['subject']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
try:
send_mail(subject, message, from_email, ['admin#example.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
# return redirect('success')
return redirect('PostList') #another view from another app
return render(request, "contact.html", {'form': form})
# def successView(request):
# return HttpResponse('Success! Thank you for your message.')
contact/urls.py
from django.contrib import admin
from django.urls import path
from .views import contactView
urlpatterns = [
path('contact/', contactView, name='contact'),
# path('success/', successView, name='success'),
]
blog/views.py
from django.views import generic
from .models import Post, PostImage
# Create your views here.
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'post_detail.html'
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet of all the books
# context['image_list'] = PostImage.objects.all()
# context['image_list'] = self.get_object().postimage_set.all()
context['image_list'] = PostImage.objects.filter(post__slug=self.kwargs.get('slug'))
return context
blog/urls.py
from . import views
from django.urls import path
urlpatterns = [
path('', views.PostList.as_view(), name='home'),
path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'),
]
I need the following in the SIMPLEST DRY manner possible; how do I write this redirect inside contact/views.py?
return redirect('PostList') #another view from another app
PostList is a class-based view from another app called blog. It is the homepage essentially.
for reference..
https://ordinarycoders.com/blog/article/django-messages-framework
In your project folder (eg, my_project/my_project) you should have a urls.py with something like this
path("admin/", admin.site.urls),
path("", include("blog.urls")),
path("", include("contact.urls"))
This allows django to look through all url files in the order listed. So long as all your url names and patterns are unique, then your view should be able to simply do
from django.shortcuts import redirect
from django.urls import reverse
return redirect(reverse('home'))
'home' being the name value of the ListView.
(NB: if you have various applevel urls.py files with path(''... django will take the first one it hits)

How do I fix the NoReverseMatch Django error?

I am trying to complete a CS50 Project, I want to render a HTML page, the template is in respective templates/encyclopedia directory.
The error page for url 127.0.0.1:8000/wiki/HTML says NoReverseMatch at wiki/HTML.
Reverse for 'edit' not found. 'edit' is not a valid view function or pattern name.
The responsible URLS.py are "wiki/<str:search>" and "wiki/random".
I'm sorry but I don't want to post this long code here but I am stuck at this problem for weeks now.
I have tried many ways don't know what's wrong with this code.
The below is my URLS.py, the projects index url includes the below urls:
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("wiki/newpage", views.newpage, name="newpage"),
# path("wiki/<str:edit>/edit", views.edit, name="edit"),
path("wiki/random", views.random, name="random"),
path("wiki/<str:search>", views.search, name="search"),
path("wiki/", views.find, name="find")
]
The below is my VIEWS.py:
from django.shortcuts import render, redirect
from django.contrib import messages
import markdown2 as md
from . import util
from django import forms
import re, random as rand
def index(request):
return render(request, "encyclopedia/index.html", {
"entries": util.list_entries()
})
def search(request, search):
if search in util.list_entries():
html = md.markdown(util.get_entry(search))
return render(request, "encyclopedia/search.html", {
"search": search, "html": html
})
else:
return render(request, "encyclopedia/error.html")
def random(request):
randomPage = rand.choice(util.list_entries())
if randomPage in util.list_entries():
html = md.markdown(util.get_entry(randomPage))
return render(request, "encyclopedia/search.html", {
"random": randomPage, "html": html
})
else:
return render(request, "encyclopedia/error.html")
def find(request):
if request.method == "GET":
query = request.GET.get('q')
for queryMatch in util.list_entries():
if query.casefold() == queryMatch.casefold():
html = md.markdown(util.get_entry(query))
return render(request, "encyclopedia/search.html", {
"queryMatch": queryMatch, "html": html
})
regex = re.compile(query.casefold())
matchList = []
for a in util.list_entries():
if regex.match(a.casefold()):
matchList.append(a)
if not matchList:
matchList = util.list_entries()
return render(request, "encyclopedia/list.html", {
"match": matchList
})
class NewPageForm(forms.Form):
title = forms.CharField(label="Title")
content = forms.CharField(label="Markdown Content", widget=forms.Textarea(attrs={'cols': '100'}))
def newpage(request):
if request.method == "POST":
form = NewPageForm(request.POST)
if form.is_valid():
title = form.cleaned_data["title"]
content = form.cleaned_data["content"]
if title in util.list_entries():
messages.error(request, f"'{title}' page title already exists!!\nPlease type another title.")
return render(request, "encyclopedia/newpage.html", {
"form": form
})
else:
util.save_entry(title, content)
return redirect(f"/wiki/{title}")
else:
return render(request, "encyclopedia/newpage.html", {
"form": form
})
return render(request, "encyclopedia/newpage.html", {
"form": NewPageForm()
})
# def edit(request, edit):
# entry = util.get_entry(edit)
Have you include your app.urls in project.urls?
Including other URLconfs
Some example from Django tutorial:
polls/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
mysite/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]

How to make custom 404 page for the Detail view with <int:pk>, if the instance not found?

so the error is Page not found(404) when I am requesting the instance that does not exist. I would like to customize the 404 page, instead of displaying the general error.
Here is my new_wiki/urls
from django.urls import path
from . import views
from .views import IndexView, InstanceView, AddPostView, EditPost
urlpatterns = [
# path('', views.index, name="index")
path('', IndexView.as_view(), name="index"),
path('instance/<int:pk>', InstanceView.as_view(), name="instance"),
path('create_post/', AddPostView.as_view(), name="create_post"),
path('instance/edit/<int:pk>', EditPost.as_view(), name="edit_post")
]
And my InstanceView class
class InstanceView(DetailView):
model = Post
template_name = 'new_wiki/instance.html'
I have tried to use the solution from Django documentation:
def detail(request, post_id):
try:
p = Post.objects.get(pk=post_id)
except Post.DoesNotExist:
raise Http404("Poll does not exist")
return render(request, 'new_wiki/instance.html', {'post': p})
but it is still returning the same 404 page. Thank you
You can just render a page with a 404 status:
def detail(request, post_id):
try:
p = Post.objects.get(pk=post_id)
except Post.DoesNotExist:
return render(request, 'new_wiki/404error.html', status=404)
return render(request, 'new_wiki/instance.html', {'post': p})
If you want to specify a custom 404 page in general, you specify the handler404 [Django-doc] in the urls.py:
from django.urls import path
from . import views
from .views import IndexView, InstanceView, AddPostView, EditPost
urlpatterns = [
# path('', views.index, name="index")
path('', IndexView.as_view(), name="index"),
path('instance/<int:pk>', InstanceView.as_view(), name="instance"),
path('create_post/', AddPostView.as_view(), name="create_post"),
path('instance/edit/<int:pk>', EditPost.as_view(), name="edit_post")
]
handler404 = views.handler404
In the view you can then analyze the exception parameter and return a specific
# app/views.py
from django.http import HttpResponseNotFound
def handler404(request, exception):
data = exception.args
if data:
return HttpResponseNotFound(data[0])
return HttpResponseNotFound('some text')
This then works if you set the DEBUG setting [Django-doc] to False:
# settings.py
DEBUG = False
In that case the handler will be invoked when you raise a Http404.
Please use get_object_or_404 method
from django.shortcuts import get_object_or_404
def detail(request, post_id):
p = get_object_or_404(Post,pk=post_id)
return render(request, 'new_wiki/instance.html', {'post': p})
Please check this is working.

Redirecting to particular page after authentication from views.py

I have three Html pages home.html, destination.html and login.html.
Home.html has only a button,if I click on this button and if the user is authenticated than he will be redirected to destination.html otherwise to login.html (I am using builtin login function and that's working properly), When user is logged in the particular username appears on home.html page,but when I click again on button it redirects again to the login.html.
views.py
This is views section for home.html and destination.html, I have use builtin function for authentication.
from django.contrib import auth
from django.shortcuts import redirect, render
from rest_framework.permissions import IsAuthenticated
def home(request):
if request.method == 'POST':
user = auth.authenticate()
if user is IsAuthenticated:
return render(request, 'destination.html')
else:
return redirect('login/')
else:
return render(request, 'home.html')
def destination(request):
return render(request, 'destination.html')
urls.py
from django.contrib import admin
from django.urls import path
from newapp import views
from django.contrib.auth.views import LoginView
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home, name='home'),
path('destination', views.destination, name= 'destination'),
path('login/', LoginView.as_view(template_name='login.html')),
]
Try this:
from django.contrib import auth
from django.shortcuts import redirect, render
from rest_framework.permissions import IsAuthenticated
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
def home(request):
if request.method == 'POST':
user = authenticate()
if user is not None:
login(request, user)
return render(request, 'destination.html')
else:
return redirect('login/')
else:
return render(request, 'home.html')
#login_required
def destination(request):
return render(request, 'destination.html')
Here we are checking user in None or not and then starting a session due to which the data created won't go be available until that particular user is logged in.
Don't forget to mention LOGIN_URL="/login/"in settings.py which will help in preventing users going to destination.html by url manipulation.
It will only be possible if the session is ON.

Django SyntaxError: invalid syntax 'else' statement?

for god sake I can't understand why I'm getting this error, it looks to be simple stuff but I've made a lot of modifications now and don't know what exactly caused this:
(from Traceback):
File "C:\Users\Lucas Cyrne Ferreira\Desktop\django- tutorial\mysite\contas\urls.py", line 2, in <module>
from . import views
File "C:\Users\Lucas Cyrne Ferreira\Desktop\django-tutorial\mysite\contas\views.py", line 38
else:
^
SyntaxError: invalid syntax
from django.shortcuts import render, redirect, HttpResponse
from contas.forms import (
RegistrationForm,
EditPerfilForm,
)
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserChangeForm, PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.decorators import login_required
def home(request):
return render(request, 'contas/home.html')
def register(request):
if request.method=='POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect(reverse('home:home'))
else:
form = RegistrationForm()
args = {'form':form}
return render(request, 'contas/reg_form.html', args)
def view_perfil(request):
args = {'user': request.user}
return render(request, 'contas/perfil.html', args)
def edit_perfil(request):
if request.method=='POST':
form = EditPerfilForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect(reverse('home:perfil')
else:
form = EditPerfilForm(instance=request.user)
args = {'form':form}
return render(request, 'contas/edit_perfil.html', args)
def trocar_password(request):
if request.method=='POST':
form = PasswordChangeForm(data=request.POST, user=request.user)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
return redirect(reverse('home:perfil')
else:
return redirect(reverse('home:trocar_password'))
else:
form = PasswordChangeForm(user=request.user)
args = {'form': form}
return render(request, 'contas/trocar_password.html', args)
My contas\urls.py:
from django.urls import path
from . import views
from django.contrib.auth.views import (
login,
logout,
PasswordResetView,
PasswordResetDoneView,
PasswordResetConfirmView,
PasswordResetCompleteView,
)
app_name = 'contas'
urlpatterns = [
path('', views.home, name='home'),
path('login/', login, {'template_name': 'contas/login.html'}, name='login'),
path('logout/', logout, {'template_name': 'contas/logout.html'}, name='logout'),
path('register/', views.register, name='register'),
path('perfil/', views.view_perfil, name='view_perfil'),
path('perfil/edit/', views.edit_perfil, name='edit_perfil'),
path('trocar-password/', views.trocar_password, name='trocar_password'),
path('reset-password/', PasswordResetView.as_view(), {'template_name': 'contas/reset_password.html', 'post_reset_redirect': 'contas:password_reset_done'},
name='reset_password'),
path('reset-password/done/', PasswordResetDoneView.as_view(), name='password_reset_done'),
path('reset-password/confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/',
PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset-password/complete/', PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]
Please help me guys, I was in the middle of a namespace tutorial... now I'm stuck on this.
You've got a missing closing parenthesis in line 39:
return redirect(reverse('home:perfil') # missing )
I'd definitely recommend using a linter such as flake8 in your project and finding a plugin for whatever code editor or IDE you use. It will find errors like and save you a lot of grief in the long run.