In my project, I have a Django form, which I then pass to my template. This form allows users to Signup for an account.
If the user makes a mistake, I use Django messages to return an error to the user, and then redirect to the same page with the error. This error is successfully displayed.
However all the previous data the user entered into the form is lost. What I want is too reload the page with the form filled in with all the previous data the user entered. This way they can correct the data easily without having to re-enter all the information again.
Does Anybody know how to accomplish this? Thank you.
views.py:
if form.cleaned_data['password'] != form.cleaned_data['confirmPassword']:
messages.error(request, 'Password fields do not match')
return redirect('signup')
else:
try:
user = User.objects.get(username=form.cleaned_data['username'])
messages.error(request, 'Username has already been taken')
return redirect('signup')
Template:
{% if messages %}
{% for message in messages %}
<span class="errorMessageSignup"> <img src="{% static 'wrongcross.png' %}" style="position:absolute;" height="17px" width="17px"> <b>{{ message }}</b></span>
{% endfor %}
{% endif %}
You can try like this in your template where you have form .
<input type="text" name="username" {% if form.username.value %} value="{{form.username.value}}" {% endif %}>
<input type="password" name="password" {% if form.password.value %} value="{{form.password.value}}" {% endif %}>
You need to save the username and password data and pass them to the template wherever you render it.
This little guide should help you :)
Related
I have multiple form on a page in modals: 1-st to create a new user address and n-forms with addresses which user created (created with loop). When i enter invalid data in fields with validators (e.g. datarequired), i have error messages in each form.
Here is the field render example which i use in every form:
{{ address_form.street.label(class_="form-label", for="InputStreet") }}
{{ address_form.street(class_="form-control", id="InputStreet") }}
{% for error in address_form.street.errors %}
<span style="color: red;">{{ error }}</span>
{% endfor %}
Part of the code from view.py:
#bp.route('/profile/address', methods=['GET', 'POST'])
#login_required
def address():
address_form = AddressForm()
if address_form.submit_address.data and address_form.validate():
address_to_add = Address(
street=address_form.street.data,
house=address_form.house.data,
building=address_form.building.data,
entrance=address_form.entrance.data,
floor=address_form.floor.data,
apartment=address_form.apartment.data,
additional_info=address_form.additional_info.data,
user=current_user)
db.session.add(address_to_add)
db.session.commit()
return redirect(url_for('profile.address'))
if address_form.edit_address.data and address_form.validate():
address_to_edit = Address.query.get(address_form.address_id.data) # Here is data from hidden field
# Editing data in DB
db.session.commit()
return redirect(url_for('profile.address'))
return render_template('profile/address.html', title='Адрес доставки', address_form=address_form)
Forms work fine with adding, editing and deleting data, but work incorrect with validation errors.
I think i need one more condition in if statenent related with hidden field or change something in my html file.
I've tried add an action attr in form like:
<form action="{{ url_for('profile.address', form_id=address.id) }}" method="post" novalidate>
And smth like this in view func but it doesn't work:
form_id = request.args.get('form_id', type=int)
if address_form.edit_address.data and address_form.validate() and form_id == address_form.address_id.data:
pass
Finally i found a very bad solution:
address_form = AddressForm()
form_id = request.args.get('form_id', 0, type=int)
For main form form_id always is 0.
Form tag for main form:
<form action="{{ url_for('profile.address', form_id=form_id) }}" method="post" novalidate>
And a field render for main form:
{{ address_form.street.label(class_="form-label", for="InputStreet") }}
{{ address_form.street(class_="form-control", id="InputStreet") }}
{% if form_id == 0 %}
{% for error in address_form.street.errors %}
<span style="color: red;">{{ error }}</span>
{% endfor %}
{% endif %}
If someone has a better solution about my problem it'd good. Now it's time to learn some JS and solve this problem with AJAX.
I am extremely new to Django's framework and recently finished the introductory series on their website, and I have tried adding a new view in which I use a form to create an object.
The problem is, whenever I access the view, it immediately executes the HttpResponseRedirect(), and second of all it does not even return a response.
views.py
def create(request):
context = {
'questionfields': Question.__dict__,
}
submitbutton = request.POST.get('Create', False)
if submitbutton:
new_question = Question(question_text=request.POST.get('question_text', ''), pub_date=timezone.now())
if new_question.question_text == '':
context = {
'questionfields': Question.__dict__,
'error_message': "No poll question entered."
}
del new_question
return render(request, 'polls/create.html', context)
else:
return HttpResponseRedirect(reverse('create'))
create.html
{% extends "polls/base.html" %}
{% block title %}Create a Poll{% endblock title %}
{% block header %}Create:{% endblock header %}
{% load custom_tags %}
{% block content %}
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:create' %}" method="post"> {% csrf_token %}
{% for field in questionfields %}
{% if field == 'question_text' %}
<label for="{{ field }}">{{ field|capfirst|replace }}:</label>
<input type="text" name="{{ field }}" id="{{ field }}">
<br>
{% else %}
{% endif %}
{% endfor %}
<br>
<input type="submit" value="Create" name="submit">
</form>
{% endblock content %}
I attempted to make it so if I enter text into the question_text input, when I click the submit button it creates a Question object with question_text being the entered text and the pub_date being the present time.
However, it merely gives a failed redirect.
I don't fully understand how the render() function works in a view and how its positioning in the logic affects the rendering of the view, so please excuse any of my mistakes.
I would like to know why it does not carry out any of the code from submitbutton... to else: , and how to fix this to get the view to work as intended. If anyone could help with my rendering and view problem it would be great.
Error image
You're using recursive here
return HttpResponseRedirect(reverse('create'))
In case it fails, it will redirect to this Create function again, and fail, and redirect again, again....
Try to do it like this:
def create(request):
context = {
'questionfields': Question.__dict__,
}
submitbutton = request.POST.get('Create', False)
if submitbutton:
new_question = Question(question_text=request.POST.get('question_text', ''), pub_date=timezone.now())
if new_question.question_text == '':
context = {
'questionfields': Question.__dict__,
'error_message': "No poll question entered."
}
del new_question
# Just render the page here with the initial context
return render(request, 'polls/create.html', context)
Right now I can run a query in the python shell and have it return True, but when trying to replicate in my html jinja template, I can't get it return the same True result.
I have a query that puts a Post.object.get(id=1) as a variable.
P1=Post.objects.get(id=1)
then ran:
P1.liked_by.all()
which does return results:
<QuerySet [<User: User object(10)>, <User: User object (12), <User: User
object (13)>]>
then I put a variable in for a User found in that query:
JV= User.objects.get(id=10)
This user id is found in the P1.liked_by.all() query, so now when I test to see if it is found.
JV in P1.liked_by.all()
True
Now when I try to access this in my html jinja template. I can not get it to check against it and return true. Even though I can print the values on the page.
Here is my Views.py:
def topic(request,topic_id):
if not 'u_id' in request.session:
return redirect('/')
print(request.session)
context={
"topic":Topic.objects.get(id=topic_id),
"user":User.objects.get(id=request.session["u_id"]),
"posts":Post.objects.filter(topic=topic_id),
}
return render(request, 'topic.html', context)
Here is my HTML:
{% for post in posts %}
<div class="cast-content">
<h3>Casting submit by <u>{{post.user.user_name}}!</u></h3>
<p>number of likes:{{post.liked_by.count}}</p>
<p>post id:{{post.id}}</p>
<p>user_id in session= {{user.id}}</p>
<p>liked by:{{post.liked_by.all}}</p>
<img src="{{post.image.url}}" class="post-pix" alt="...">
<br>
<p>post liked_by values: {{post.liked_by.values}}</p>
{% if user.id in post.liked_by.all %}
Un-Like
{% else %}
<form action="/add-like" method="post">
{% csrf_token %}
<input type="hidden" name="post_id" value="{{post.id}}">
<input type="hidden" name="topic" value="{{topic.id}}">
<input type="submit" value="Like">
</form>
{% endif %}
{% if user.id == post.user.id %}
Remove
{% endif %}
</div>
{% endfor %}
I can not figure out why I can print the values in the template but when I run the {% if %} statement to check if it exists in the table It can't find it therefore defaulting into the {% else %} statement every single time. Any help at all is so greatly appreciated!
I am struggling with an request.user statement in Django.
Through those all hours what I wanted to achieve is:
Only the "user" (author) of the ShiftReport (simply a post) should be able to edit the ShiftReport.
So far I have managed to do that, and when I am logged in as another user I receive an error 404, whereas logged in as a post creator I am able to edit the post - Great!.
However, instead of that 404 Error I would just like to throw a Bootstrap modal saying access denied.
My 'views.py':
def update(request, shiftreport_id=None):
title = 'Edit Shift Report by'
instance = get_object_or_404(ShiftReport, pk=shiftreport_id, user=request.user)
form = shiftreportForm(request.POST or None, request.FILES or None, instance=instance)
confirm_message = None
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
title = "Thanks"
confirm_message = "Shift Report has been updated!"
form = None
context = {
"title": title,
"instance": instance,
"form": form,
"confirm_message": confirm_message,
}
return render(request, 'shift/edit.html', context)
My 'detail.html':
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-center">
<li>New Shift Report</li>
<li>All Shift Reports</li>
{% if not request.user %}
with above statement I can edit my own post and I get Error404 when I
want to edit a post from another user.
When I change it to {% if request.user %}, my modal works but then I cannot edit any of the posts, neither mine neither from another user.
<li>Edit Shift Report Nr.{{ shiftreport.id }}</li>
<li>Delete Shift Report</li>
{% else %}
<li>Edit Shift Report Nr.{{ shiftreport.id }}</li>
<li>Delete Shift Report</li>
{% endif %}
</ul>
<form class="navbar-form navbar-right" method="GET" action="">
<input type="text" class="form-control" name="q" placeholder="Search..." value="{{ request.GET.q }}">
</form>
</div>
Hope construction of my question make sense a little, the issue on the other hand doesn't make any sense to me... would appreciate any help.
Thanks.
I am using Django in-build password to allow users to reset the password. My password_reset_form.html looks like this:
{% block title %}Reset Password{% endblock %}
{% block content %}
<p>Please specify your email address to receive instructions for resetting it.</p>
<form action="" method="post">
<div style="display:none">
<input type="hidden" value="{{ csrf_token }}" name="csrfmiddlewaretoken">
</div>
{{ form.email.errors }}
<p><label for="id_email">E-mail address:</label> {{ form.email }} <input type="submit" value="Reset password" /></p>
</form>
{% endblock %}
For now, user can enter their e-mail address and password reset instruction is send to the user. I want to modify this so that user can enter either their username or e-mail address and receive the password reset instruction in email. Should I directly go to dist-packages and start editing the password reset file or should I do something else?
I can find the e-mail address of user using their username if they enters their username:
if not '#' in new_mail:
email = User.objects.filter(username=new_mail).values_list('email')
new_mail1 = email[0]
How can I do this? Thank you
You definitely should not edit dist-packages files. Built-in views and forms don't support the behaviour you want. I think it's ok to copy implementation of the involved views and forms and modify them. Copy django.contrib.auth.views.password_reset view to your views file. Copy django.contrib.auth.forms.PasswordResetForm to your forms file and add username field to it and modify user search code to search on email or username depending on what has been specified. Change used form class in password_reset view to your new PasswordResetForm. This should be enough.
I'd do something like this
{% block title %}Reset Password{% endblock %}
{% block content %}
<p>Please specify your username or email address to receive instructions for resetting it.</p>
<form action="" method="POST">
{% csrf_token %}
{{ form.email.errors }}
<p>{{ form.email.label }}{{ form.email }} <button type="submit">Reset Password</button></p>
</form>
{% endblock %}
In your POST variable you now have an email or a password. You'd have to make a guess if people would use the email or username more. Based on that the following should work
from django.db.models import Q
email = request.POST.get('email, "")
u = User.objects.filter(Q(username=email)|Q(email=email))
if u.count() == 1:
email_address = u[0].email
# now you can send the user an email with instructions
if u.count() < 1:
# invalid username or email
return
if u.count() > 1:
# unlikely but lets account for this anyway. I'll leave this up to you
return
There might be a more elegant way to check for the user, but this way there's essentially only one query and might be quicker than matching email and username individually in try/except blocks. Personally I prefer a filter/count way of checking rather than try/except, but thats besides the point.