render template not changing the url of the page - python

I'm creating a login, register account website and it works well except for when i use the render template command as it loads the page successfully but then the url of the page is the URL of the previous page and when I refresh it, it goes back to the previous page. But when I use the redirect(url_for command I'm not able to pass variables through it
class LoginForm(FlaskForm):
username= StringField(validators=[InputRequired(),Length(min=4,max=20)],render_kw={"placeholder":"Username"})
password= PasswordField(validators=[InputRequired(),Length(min=8,max=20)],render_kw={"placeholder":"Password"})
submit =SubmitField("Login")
#app.route("/login",methods= ['GET','POST'])
def login():
form=LoginForm()
print("in login html")
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user:
if user.password==form.password.data:
login_user(user)
print("password entered")
userUsername=form.username.data
#return redirect(url_for('dashboard',userUser=userUsername,))
return render_template("dashboard.html",userUser=userUsername)
else:
print("incorrect pass")
return render_template("login.html",form=form)
#app.route("/dashboard",methods= ['GET','POST'])
#login_required
def dashboard():
return render_template("dashboard.html")
this is my python code, my dashboard.html-
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dashboard</title>
<link href = "../static/main.css" rel = "stylesheet">
</head>
<div class = "container1">
<body>
<div data-role="page" id="welcome" data-url="{{ url_for('dashboard') }}">
{%extends "layout.html"%}
{%block content%}
<p>{{userUser}}</p>
<h1>Hello you are logged in. </h1>
<div class = "container1">Welcome {{userUser}}!</div>
<form action ="{{url_for('login')}}" method = POST>
<br> <button type = "submit">Logout</button>
</form>
</div>
{%endblock%}
</body>
</html>
now my login.html
<!DOCTYPE html>
<html lang = "en">
<head>
<link href = "../static/main.css" rel = "stylesheet">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
</head>
<body>
<div class = "container">
<h1>Login</h1>
<form method="POST" actions="">
{{ form.hidden_tag() }}
{{ form.username }}
{{ form.password }}
{{ form.submit }}
</form>
Don't have an account? Sign Up
<div class = "message"> {{errorMessage | safe}}</div>
</div>
</body>
</html>
when i pass userUser through redirect(url_for it doesnt work but with render templates it does but the url remains /login

Related

Django file upload returns None

I'm trying to learn Python and Django, when I try to upload a file in my form Django detect my file as "None".
forms.py:
from django import forms
class FormularioTrabajo(forms.Form):
email = forms.EmailField(label="Correo Electrónico:", max_length=254)
Currículum = forms.FileField()
views.py:
In views I want to save the file uploaded in the directory /media/
def trabaja(request):
if request.method == 'POST':
form = FormularioTrabajo(data=request.POST, files=request.FILES)
if form.is_valid():
file = request.FILES.get('file', None)
if file is not None:
file_name = file.name
file_path = '/media/' + file_name
with open(file_path, 'wb+') as destination:
for chunk in file.chunks:
destination.write(chunk)
form.save()
return HttpResponseRedirect(reverse("miapp:index"))
else:
return HttpResponse('None')
else:
form = FormularioTrabajo()
return render(request, "web/trabajar.html", {'form':form})
This is my template html:
{% load bootstrap5 %}
{% bootstrap_css %}
{% bootstrap_javascript %}
{% bootstrap_messages %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% load static %}
<link rel="stylesheet" href="{% static '/style.css' %}">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<title>Trabaja con nosotros</title>
</head>
<body>
<header>
<br>
<ul>
<li>Conócenos</li>
<li>Inicio de Sesión</li>
<li>Registro de usuario</li>
<li>Contacta con nosotros</li>
</ul>
{% load static %}
<img src="{% static 'img/logo.PNG'%}" class="logo">
</header>
<div class="work-box">
<h3>Solicitud de Trabajo</h3>
<form id="contactForm" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button class="btn btn-primary btn-lg" type="submit">Submit</button>
{% endbuttons %}
</form>
</div>
</body>
</html>
Please correct this line
if form.is_valid():
file = request.FILES.get('Currículum', None)

Page not found (404) Request Method: POST

I've been stuck with this error for a few days and am not able to find where the mistake is.
views section
from django.shortcuts import render,redirect
from django.contrib.auth.models import User,auth
# Create your views here.
def register(request):
if(request.method=='POST'):
username=request.POST['username']
password1=request.POST['password1']
password2=request.POST['password2']
user=User.objects.create_user(username=username,password=password1)
user.save();
print("user created")
return redirect('/')
else:
return render(request,'registration.html')
urls.py section
from django.urls import path
from . import views
urlpatterns=[path('register/',views.register,name="register")]
html section
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registration</title>
</head>
<body>
<form action="register" method="POST">
{% csrf_token %}
USERNAME <input type="text" name="username" id=""> <br><br>
PASSWORD <input type="password" name="password1" id=""> <br><br>
RETYPE PASSWORD <input type="password" name="password2" id=""> <br><br>
<input type="submit" value="">
</form>
</body>
</html>
Issue
create_user() doesn't require save() method to be called for creating instance.
You have given only action="register" which is not valid at all, you need to give url tag, to perfectly make route. That's the case for page not found which is the main question.
So, with some modifications try below code:
Views.py
def register(request):
if(request.method=='POST'):
username=request.POST['username']
password1=request.POST['password1']
password2=request.POST['password2']
user=User.objects.create_user(username=username,password=password1)
print("user created")
return redirect('/')
else:
return render(request,'registration.html')
Template file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registration</title>
</head>
<body>
<form action="{% url 'register' %}" method="POST">
{% csrf_token %}
USERNAME <input type="text" name="username" id=""> <br><br>
PASSWORD <input type="password" name="password1" id=""> <br><br>
RETYPE PASSWORD <input type="password" name="password2" id=""> <br><br>
<input type="submit" value="Save">
</form>
</body>
</html>

Django Form request method is always GET, even method=“POST” is mentioned in HTML template

Please help me with this query. I have a project to work on...
Thanks!!
HTML file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<form method="post" class="post-form" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</body>
</html>
Views.py file
You should add "action" attribute to your form so that the server can choose where to post the data. Add this attribute to your form tag:
action="{% url 'url_name' %}"
url_name here is the name in urlpatterns to receive a request from the form
For example:
urlpatterns = [
path('url_name/', views.index, name = 'url_name'),
]
Views:
def index(request):
if request.method == 'POST':
print("Valid")
student = Studentform(request.POST, request.FILES)
if student.is_valid():
handle_uploaded_file(request.FILES['file'])
student.save() # <== HERE
return HttpResponse('File uploaded successfully')
else:
return HttpResponse('Not uploaded')
else:
student = Studentform()
return render(request, 'name_of_your_upload.html', {'student': student})
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<form method="post" class="post-form" enctype="multipart/form-data">
{% csrf_token %}
{{ student.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</body>
</html>

Django - Save Form Value in Different Views

I'm trying to create a small app in which a user can view an event, submit a form indicating the quantity of tickets they would like, view their basket and finally go to a checkout page.
My problem is that after I submit a form for event1, the value that is posted is lost when I try to view another event or refresh the basket. How can I prevent this from happening? I need to use Django to make use of a python module during the checkout process so I need to be able to retrieve the quantities submitted for any event in the final checkout view.
My views.py file:
def basket(request):
context = {'Event 1 Tickets': event1_tickets, 'Event 2 Tickets': event2_tickets}
return render(request, 'first_app/basket.html', context)
def event2(request):
form = forms.TicketForm()
form = forms.TicketForm(request.POST)
if request.POST:
if form.is_valid():
# form.save(commit=True)
quantity = form.cleaned_data['quantity']
return render(request,'first_app/basket.html',{'event2_tickets': form.cleaned_data})
else:
form = TicketForm()
return render(request, 'first_app/event2.html', {'form': form})
def event1(request):
form = forms.TicketForm()
form = forms.TicketForm(request.POST)
if request.POST:
if form.is_valid():
# form.save(commit=True)
quantity = form.cleaned_data['quantity']
return render(request,'first_app/basket.html',{'event1_tickets': form.cleaned_data})
else:
form = TicketForm()
return render(request, 'first_app/event1.html', {'form': form})
My forms.py:
from django import forms
class TicketForm(forms.Form):
quantity = forms.IntegerField(label="Ticket Quantity",min_value=1,max_value=9,required=True, widget=forms.NumberInput)
My event1/event2.html:
<!DOCTYPE html>
{% load static %}
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="{% static "css/style.css" %}"/>
</head>
<body>
<div class="topnav">
<a class="" href="{% url 'index' %}">Home</a>
Basket
</div>
<div>
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
My static basket.html:
<!DOCTYPE html>
{% load static %}
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="{% static "css/style.css" %}"/>
<!-- <script src="{% static "javascript/script.css" %}"/></script> -->
</head>
<body>
<div class="topnav">
Home
<a class="active" href="{% url 'basket' %}">Basket</a>
</div>
<div>
<h1>Tickets for Event 1 {{ event1_tickets.quantity }}</h1>
<h1>Tickets for Event 2 {{ event2_tickets.quantity }}</h1>
</div>
<button type="button" class="button" onclick = "window.location.href='{% url 'checkout' %}' ">Checkout</button>
</body>
</html>
My urls.py file:
from django.conf.urls import url
from django.urls import path
from . import views
urlpatterns = [
path('checkout/', views.checkout, name='checkout'),
path('basket/', views.basket, name='basket'),
path('event1/', views.event1, name='event1'),
path('event2/', views.event2, name='event2'),
]

Render_to_string and response.content.decode() not matching

I'm writing my first Django app by following along with this book:
http://chimera.labs.oreilly.com/books/1234000000754/ch05.html#_passing_python_variables_to_be_rendered_in_the_template
In the book there is a test that is verifying that the html is being returned as it is supposed to. Here is the test:
def test_home_page_returns_correct_html(self):
request = HttpRequest()
response = home_page(request)
expected_html = render_to_string('home.html')
print(expected_html)
print(response.content.decode())
self.assertEqual(response.content.decode(), expected_html)
My test is failing on the assertEqual test because I have added a csrf token in my HTML using the Django Template Language. Here is what my HTML page looks like:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To-Do lists</title>
</head>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item"/>
{% csrf_token %}
</form>
<table id="id_list_table">
<tr><td>{{ new_item_list }}</td></tr>
</table>
</body>
</html>
My assert is failing due to the render_to_string method not including the token. Here is what my two print statements included in my test print out:
F<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To-Do lists</title>
</head>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item"/>
</form>
<table id="id_list_table">
<tr><td></td></tr>
</table>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To-Do lists</title>
</head>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item"/>
<input type='hidden' name='csrfmiddlewaretoken' value='VAiGvXZLHCjxWEWdjhgQRBwBSnMVoIWR' />
</form>
<table id="id_list_table">
<tr><td></td></tr>
</table>
</body>
</html>
F.
He doesn't have this problem in the book (he's using 1.8), so I was wondering if the method behavior has changed, or how I would write this test to pass.
The request argument was added to render_to_string in Django 1.8. You could try changing the line in your test to:
expected_html = render_to_string('home.html', request=request)
It's only required to make this change in Django 1.9+, the test passes without the request in Django 1.8.
I found this solution which has worked for the latest Django version - 3.0.6
#add a function to the post request test function
def remove_csrf_tag(text):
"""Remove csrf tag from TEXT"""
return re.sub(r'<[^>]*csrfmiddlewaretoken[^>]*>', '', text)
...
# then change assertion
def test_home_page_can_save_a_POST_request(self):
...
self.assertEqual(
remove_csrf_tag(response.content),
remove_csrf_tag(expected_html)
)

Categories