Django not redirecting to next page - python

I don't know what's happening with my code, once a user that is not authenticated tries to access a page and it redirects to the login page, I can see the next parameter in the browser but after the user logins, it takes the user to the default LOGIN_REDIRECT_URL and not the next page. Also on the template next returns none, so seems the template is not getting thee next value, but in the url it shows the /?next=, thanks in advance.
urls.py
from django.contrib import admin
from django.urls import path, include
from django.contrib.auth import views as auth_views
from blog import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.HomeView.as_view(),name="index"),
path('accounts/login/', auth_views.LoginView.as_view(), name='login'),
path('accounts/logout/', auth_views.LogoutView.as_view(next_page='/'), name='logout'),
path('accounts/profile/', views.ProfileView.as_view(), name='profile'),
]
registration/login.html
{% extends 'app/base.html' %}
{% block link %} id="active" {%endblock%}
{% block content %}
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div class="jumbotron" id="font">
{% if next %}
{% if user.is_authenticated %}
<h2 class="customtext" align="center">Your account doesn't have access to this page. To proceed,
please login with an account that has access.</h2>
{% else %}
<h2 class="customtext" align="center">Please login.</h2>
{% endif %}
{% else %}
<h2 class="customtext" align="center">Enter your login details.</h2>
{% endif %}
<form action="{% url 'login' %}" method="POST">
{%csrf_token%}
<div class="form-group">
<input type="text" name="username" placeholder="username" class="form-control">
</div>
<div class="form-group">
<input type="password" name="password" placeholder="password" class="form-control">
</div>
<!-- <div align="center"> -->
{% if form.errors %}
<!-- <p style="color: red; font-style: italic;">Your username or email is does not match.</p> -->
{{form.errors}}
{% endif %}
<!-- </div> -->
<div class="loginbtndiv" align="center">
<input type="submit" class="btn btn-warning btn-lg loginbtn" value="LOGIN">
</div>
<input type="hidden" name="next" value="{{ next }}">
</form>
</div>
</div>
<div>
</div>
</div>
{% endblock %}

Related

flask url_for in href is not redirecting to the correct flask method and rendering wrong page

I have a flask application I am building. I have two methods/routes that do two different things. one route redirects to profile.html and the second route is supposed to redirect to update_profile.html
my issues is that in my profile html file, there is an edit profile link that uses url_for('views.profile_update') to redirect to the profile_update route/method. when I click the link, it just renders the same profile page that is part of the profile method rather than profile_update method. Not sure why this is happening...
views.py
from flask import Blueprint, render_template, session, redirect, url_for, request
from . import db
views = Blueprint('views', __name__)
#views.route('/profile', methods=(['GET']))
def profile():
if 'username' in session:
print('profile page')
print(session['username'])
loggedInUser = db.users.find_one({'username': session['username']})
return render_template('profile.html', loggedInUser=loggedInUser)
else:
return redirect(url_for('auth.login'))
#views.route('/profile', methods=['GET', 'POST'])
def profile_update():
if 'username' in session:
print('profile update')
return render_template('update_profile.html')
else:
return redirect(url_for('auth.login'))
profile.html
{% extends 'base.html' %}
{% block title %} PROFILE {% endblock %}
{% block navbar %}
<a class="nav-item nav-link" id="feed" href="/">Feed</a>
<a class="nav-item nav-link" id="activity" href="/">Activity</a>
<a class="nav-item nav-link" id="photos" href="/">Photos</a>
<a class="nav-item nav-link" id="edits" href="/">Edits</a>
<a class="nav-item nav-link" id="profile" href="/profile">Profile</a>
<a class="nav-item nav-link" id="logout" href="/auth/logout">Logout</a>
{% endblock %}
{% block content %}
<p>{{ loggedInUser.profile_pic }}</p>
<h1>{{ loggedInUser.username }}</h1>
<p>{{ loggedInUser.following }}</p>
<p>{{ loggedInUser.followers }}</p>
<p>{{ loggedInUser.email }}</p>
<p>{{ loggedInUser.name }}</p>
<p>{{ loggedInUser.location }}</p>
<p>{{ loggedInUser.bio }}</p>
<p>{{ loggedInUser.photo_list }}</p>
<p>{{ loggedInUser.edit_list }}</p>
<a class="nav-item nav-link" id="update_profile" href={{ url_for('views.profile_update') }}>Edit Profile</a>
{% endblock %}
update_profile.html
{% extends 'base.html' %}
{% block title %} UPDATE PROFILE {% endblock %}
{% block navbar %}
<a class="nav-item nav-link" id="feed" href="/">Feed</a>
<a class="nav-item nav-link" id="activity" href="/">Activity</a>
<a class="nav-item nav-link" id="photos" href="/">Photos</a>
<a class="nav-item nav-link" id="edits" href="/">Edits</a>
<a class="nav-item nav-link" id="profile" href="/profile">Profile</a>
<a class="nav-item nav-link" id="logout" href="/auth/logout">Logout</a>
{% endblock %}
{% block content %}
<form actions="/auth/signup" method="POST">
<header>Sign Up</header>
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" defaultValue="Enter Username"/>
<label for="password">Password</label>
<input type="password" for="password" name="password" defaultValue="Enter Password"/>
<label for="password-confirm">Confirm Password</label>
<input type="password" for="password-confirm" name="password-confirm" defaultValue="Confirm Password"/>
<label for="email">Email</label>
<input type="email" for="email" name="email" defaultValue="Enter Email"/>
<label for="name">Name</label>
<input type="text" for="name" name="name" defaultValue="Enter Name"/>
<label for="account">Account</label>
<select name="account">
<option value="photographer">Photographer</option>
<option value="videographer">Videographer</option>
<option value="editor">Editr</option>
<option value="designer">Designer</option>
</select>
<label for="bio">Bio</label>
<input type="text" for="bio" name="bio" defaultValue="Enter Bio"/>
<label for="location">Location</label>
<input type="text" for="location" name="location" defaultValue="Enter City, State"/>
<input type="submit" name="submit" value="Sign Up"/>
</div>
</form>
{% endblock %}
What is supposed to happen is that when you get the profile.html file and click on the edit profile link, it is supposed to redirect to the profile_update and then render the update_profile.html file. Right now, it just keeps rendering the profile.html file. When i redirect it to something like home page, it works correctly. The profile_update is the only method/route that is not working.
The issue is that you are using the same url for both routes:
#views.route('/profile', methods=(['GET']))
def profile():
...
#views.route('/profile', methods=['GET', 'POST'])
def profile_update():
...
You could fix this by changing the profile_update url to something like this:
#views.route('/profile/update', methods=['GET', 'POST'])
def profile_update():
...

Why my url in "not matching any url" when it is? I have no idea how to fix it, am I doing something wrong?

Im not gonna lie, this doesnt make any sense to me, why is this trying to access 'post-details' instead of 'create-post' and how do I fix it? Thank you in advance
error:
NoReverseMatch at /create/
Reverse for 'post-details' with arguments '('',)' not found. 1 pattern(s) tried:
['(?P[-a-zA-Z0-9_]+)/post/$']
Request Method: GET
Request URL: http://127.0.0.1:8000/create/
Django Version: 3.2.2
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'post-details' with arguments '('',)' not found. 1 pattern(s) tried: ['(?P[-a-zA-Z0-9_]+)/post/$']
Post create view:
class PostCreate(CreateView):
model = Post
form_class = PostCreateForm
template_name = 'post/post_create.html'
context_object_name = 'form'
def get_success_url(self):
return reverse('post:home')
def form_valid(self, form):
form.instance.author = self.request.user.profile
return super().form_valid(form)
My urls:
from django.urls import path, include
from . import views
app_name = 'post'
urlpatterns = [
path('', views.PostList.as_view(), name='home'),
path('<slug:slug>/post/', views.PostDetails.as_view(), name='post-details'),
path('search/', views.search, name='search'),
path('comment-delete/<pk>/', views.CommentDelete.as_view(), name='comment-delete'),
path('comment-update/<pk>/', views.CommentUpdate.as_view(), name='comment-update'),
path('tag/<str:name>/', views.PostTagList.as_view(), name='tag-posts'),
path('create/', views.PostCreate.as_view(), name='create-post')
]
post_create.html file from my PostCreate view:
{% extends 'base.html' %}
{% block content %}
<div class="container mt-5 mb-5">
<form action="" class="commenting-form" method="post" enctype="multipart/form-data">
<div class="row">
<div class="form-group col-md-12">
{% csrf_token %}
{{ form.tags }}
<div class="form-group col-md-12">
<button type="submit" class="btn btn-secondary mt-2">Edit comment</button>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-12">
{% csrf_token %}
{{ form.body }}
{{ form.picture }}
<div class="form-group col-md-12">
<button type="submit" class="btn btn-secondary mt-2">Edit comment</button>
</div>
</div>
</div>
</form>
<hr>
<a class="btn btn-info" href="{% url 'post:post-details' post_slug %}">Back</a>
</div>
{% endblock content %}
How im passing the slug value to the 'post-details'
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="container">
<div class="row">
<!-- Latest Posts -->
<main class="posts-listing col-lg-8">
<div class="container">
<div class="row">
{% for post in posts %}
<div class="post col-xl-6">
<div class="post-thumbnail">
<a href="{% url 'post:post-details' post.slug %}">
<img src="{{ post.picture.url }}" alt="..." class="img-fluid post-picture">
</a>
</div>
<div class="post-details">
<div class="post-meta d-flex justify-content-between">
<div class="date meta-last">{{ post.created|timesince }}</div>
<div class="category">
{% for tag in post.tags.all %}
{{ tag }}
{% endfor %}
</div>
</div>
<p class="text-muted">{{ post.body }}</p>
<div class="post-footer d-flex align-items-center"><a href="#"
class="author d-flex align-items-center flex-wrap">
<div class="avatar"><img src="{{ post.author.avatar.url }}" alt="..." class="img-fluid"></div>
<div class="title"><span>{{ post.author }}</span></div>
</a>
<div class="comments meta-last"><i class="icon-comment"></i>{{ post.get_comment_number }}</div>
</div>
</div>
</div>
{% endfor %}
</div>
<!-- Pagination -->
</div>
</main>
{% include 'sidebar.html' with common_tags=common_tags latest_posts=latest_posts %}
</div>
</div>
{% endblock content %}

Using App name with Django.contrib.auth views

I am new to Django and I am creating a user change password page. However, I keep encountering a NoReverseMatch error which I suspect is due to my app name but I am not able to resolve it even after spending hours googling for a solution.
My urls.py file:
from os import name
from django.urls import path
from account import views
from django.contrib.auth import views as auth_views # Import Django built-in authentication views
app_name = 'account'
urlpatterns = [
path('test/', views.test_login, name='test'),
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
path('password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
]
My settings.py:
# Login Logic
LOGIN_REDIRECT_URL = 'account:test' # Tells Django which URL to redirect user to after a successful login if no next parameter is present in the request
LOGIN_URL = 'account:login' # The URL to redirect the user to log in - based on the name in the urls.py
LOGOUT_URL = 'account:logout' # The URL to redirect the user to log out - based on the name in the urls.py
my html file
{% extends "base.html" %}
{# This is the template to allow user to change their password #}
{% block title %}Change Your Password{% endblock title %}
{% block content %}
<div class="container">
<div class="row justify-content-center">
<div class="col-8">
<form action="{% url 'account:password_change_done' %}" class="form-signin" method="post">
{% csrf_token %}
<h1 class="h3 mb-3 font-weight-normal text-center">Change your password</h1>
<div class="form-group">
<label for="old_password">Old Password</label>
<input class="form-control" type="password" required id="id_old_password" name="old_password" autocomplete="current-password" placeholder="Old Password" autofocus>
</div>
<div class="form-group">
<label for="new_password1">New Password</label>
<input class="form-control" type="password" required id="id_new_password1" name="new_password1" autocomplete="new-password" placeholder="New Password">
</div>
<div class="form-group">
<label for="new_password2">Confirm Password</label>
<input class="form-control" type="password" required id="id_new_password2" name="new_password2" autocomplete="new-password" placeholder="Confirm Password">
</div>
<small class="form-text text-muted">
{% if form.new_password1.help_text %}
{{ form.new_password1.help_text|safe }}
{% endif %}
</small>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
{% endblock content %}
Much help is appreciated.
Have added in the html file for referece
A "NoReverseMatch" error means , Django is not being able to process and see the exact url being passed.
Including the "app_name" has said by most Django devs makes the code neat and easy to streamline to as to which url you want and most importantly helps to avoid duplicating urls..
An instance will be having this url path of "home" in your app accounts and also having that same path "home" in some other app, the use of specifying the app_name will help Django , include the urls to their respective apps so you know which requires which .
Your urls are correct to me and since it's a NoReverseMatch error, it will have to be your at your html or view or anywhere where you are calling a url.
Try including the app name in either your html and view on where you are calling the url..
Something like this
{% app_name:name_url %}
And same to the view app_name:name_url
Always make sure there is semi-colon between the app_name and the url ... As it will help you tell Django as to which url from which app!!

request.POST.get returns NULL

I'm trying POST my text value from my HTML form to Django view but always get NONE as a result.
Initially, I was trying to fetch value by request.POST which threw "MultiValueDictKeyError" then I changed my code to request.POST.get which is returning None
HTML file
{% csrf_token %}
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1" style="margin-top: 5px">
<ul class="nav navbar-nav">
<li class="dropdown" style="padding-right: 10px">
<select class="form-control" id="sel1" style="font-family: Courier">
{% for environment in env_list %}
<option name="NewEnvName"
value="{{ environment.Env_name }}">{{ environment.Env_name }}</option>
{% endfor %}
</select>
</li>
</ul>
<ul class="nav navbar-nav">
<li class="dropdown" style="font-family: Courier;font-size: 20px;color: ivory">
<input type='radio' name='CobranSelection' value="CobrandName" checked/>
<label for="edit-radios-lorem-tortor-erat" class="option"
>Cobrand
Name | </label>
<input type='radio' name='CobranSelection' value="CobrandId"/>
<label for="edit-radios-lorem-tortor-erat" class="option"
>Cobrand
Id </label>
</li>
</ul>
<div class="form-group">
<input type="text"
style="margin-top: -1px;font-family: Courier;width: 210px;margin-right: -10px"
class="form-control"
name="cobrand" placeholder="Eneter Cobrand detail here">
<button type="submit" class="btn btn-default"
style="margin-top: -31px;font-family: Courier;margin-left: 230px">
Submit
</button>
</div>
</div><!-- /.navbar-collapse -->
</form>
view.py
from django.shortcuts import render, HttpResponseRedirect
from .models import Environments
from django.db.models import Q
import cx_Oracle
def knowcobrand(request):
value_type = request.POST.get('CobranSelection')
cobrand_value = request.POST.get('cobrand')
env = request.POST.get('NewEnvName')
print(value_type)
print(cobrand_value)
print(env)
return render(request, 'CobrandView/CobrandInDepth.html')
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url('login', views.login),
url('Home', views.fetch_all_env),
url('AddEnvironment', views.add_environment),
url('GetEnvironment', views.GetEnvironment),
url('ReadDb', views.readdb),
url('LearnCobrand', views.learncobrand),
url('ReadCobrand',views.knowcobrand)
]
I'm posting my HTML and views.py for reference. Could anyone of you please help me by pointing out my mistake.
add this attribute to your form :
enctype="multipart/form-data"
like this :
<form action="" method="post" enctype="multipart/form-data">
and attention in view side file field use request.FILES

Django: login link to appear only when a user is logged in

I am making an app in django in which i have used the django built in authentication system. Both login and logout links are present in the navbar. I want to make the logout link appear only when the user has logged in and not at all times. How do i do that?
code snippet of project/urls.py:
urlpatterns = [
url(r'^login/$', views.login, {'template_name': 'login.html', 'authentication_form': LoginForm}, name='login'),
url(r'^logout/$', views.logout, {'next_page': '/home'}), ]
code snippet of login.html;
<div class="container">
<section id="content">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<form action="{% url 'login' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<h1>Login Form</h1>
<div class="imgcontainer">
<img src="{% static 'student/patient.jpg' %}" alt="Avatar" class="avatar">
</div>
<div class="username">
{{ form.username.label_tag }}
{{ form.username }}
</div>
<div class="password">
{{ form.password.label_tag }}
{{ form.password }}
</div>
<div class="submitb">
<input type="submit" value="Log In" name="mybtn">
</div>
<div class="resetb">
<input type="submit" value="Reset">
Forgot password?
</div>
<input type="hidden" name="next" value="{{ next }}" />
</form>
code snippet of base.html(only the navbar is shown):
<ul>
<li><a class="active" href="/home">Home</a></li>
<li>About </li>
<li>Sign up</li>
<li>Doctor's login</li>
<li>Patient's login</li>
<li>FAQs</li>
<li>Contact us</li>
<li>Reviews</li>
<li>Logout</li>
</ul>
Thanks for your help in advance.
Put the logout list item in an if block that checks that the user is authenticated like so:
<ul>
...
{% if request.user.is_authenticated %}
<li>Logout</li>
{% endif %}
</ul>
Although using the variable request.user.is_authenticated is one way. To make it simpler create HTML pages such that login and logout button are disintegrated.
Pages which appear after login should only contain the logout option/button. This will smoothen your development process.

Categories