Django - Submit multiple forms with one submit button - python

I'm trying to create a check in page that lists all of the people that have signed up. Each person has an input box that submits the number of hours they were at the event. I want it so that the same form is submitted multiple times for every person; I don't want to have a submit button for every person because there will be several people and it'll be tedious. I'm using a for loop {% for signups in signup %} to loop through the queryset for the people who are signed up.
Here's a screenshot to illustrate:
In the backend, I want it to save the number of hours to the row in the queryset with the matching name.
HTML:
<form action="/events/occ_checkin" class="form" method="POST" id="checkin_{{ signups.id }}" name="checkin_{{ signups.id }}">{% csrf_token %}
{% for form in formset %}
<h5>
<label for="{{ form.fullname.id_for_label }}">***how would I get the attendee's name?***</label>
<input id="{{ form.fullname.id_for_label }}" name="{{ form.fullname.html_name }}" type="hidden" value="***attendee's name here as well***">
<input id="{{ form.hours.id_for_label }}" name="{{ form.hours.html_name }}" step="0.01" type="number" class="form-control" value="{{ events.hours }}">
</h5>
{% endfor %}
<button class="btn btn-primary btn-block" type="submit">Submit</button>
</form>

Using modelformset_factory worked.
HTML:
<form action="/events/occ_checkin" class="form" method="POST" id="checkin_{{ signups.id }}" name="checkin_{{ signups.id }}">{% csrf_token %}
{% for form in formset %}
<h5>
<label for="{{ form.fullname.id_for_label }}">{% for signups in signup %}{% if forloop.parentloop.counter == forloop.counter %}{{ signups.fullname }}{% endif %}{% endfor %}</label>
<input id="{{ form.fullname.id_for_label }}" name="{{ form.fullname.html_name }}" type="hidden" value="{% for signups in signup %}{% if forloop.parentloop.counter == forloop.counter %}{{ signups.fullname }}{% endif %}{% endfor %}">
<input id="{{ form.hours.id_for_label }}" name="{{ form.hours.html_name }}" step="0.01" type="number" class="form-control" value="{{ events.hours }}">
</h5>
{% endfor %}
<button class="btn btn-primary btn-block" type="submit">Submit</button>
</form>
For views.py and forms.py I just followed the documentation on formsets.

Related

How do I get all for-looped values from a Django template

I am new to django. I want to use this django form to get number_of_days for all {{ name }} values
<div>
<form action="change_number_of_days" method="post">
{% csrf_token %}
{% for name in filenames %}
<input type="number" name="number_of_days" id="number_of_days" value=200>
<label for="number_of_days"> {{ name }} </label>
<input type="hidden" value="{{ name }}" name="name_of_file"><br><br>
{% endfor %}
<button type="submit"> Gem </button>
</form>
</div>
Currently Im only getting the values of the LAST loop(Pizzaria, 200), but I want to get all looped inputs as a POST request
This is my VIEW.py
def change_number_of_days(request):
if request.method == 'POST':
days = request.POST['number_of_days']
print(cleaning_days)
filename = request.POST['name_of_file']
print(filename)
return render(request, 'price_calculation_complete.html')
return HttpResponse("error")
You have explicitly mentioned that - That's why it shows only 200
<input type="number" name="number_of_days" id="number_of_days" value=200>
You have to set the first <input> tag's value to {{ name }}.
<div>
<form action="change_number_of_days" method="post">
{% csrf_token %}
{% for name in filenames %}
<input type="number" name="number_of_days" id="number_of_days" value="{{ name }}">
<label for="number_of_days"> {{ name }} </label>
<input type="hidden" value="200" name="name_of_file"><br><br>
{% endfor %}
<button type="submit"> Gem </button>
</form>
</div>
I figured it out. To anyone interested:
days_list = request.POST.getlist('number_of_cleaning_days')
I had to use .getlist instead of just POST

Force a hidden input to return a fixed value

The following is my current code:
{% for comment in commentlist %} <!-- Comment section -->
<h5>
{{ comment[0] }}
</h5>
<h6>Created {{ comment[1].strftime('%d/%m/%Y at %I:%M%p') }} By: {{ comment[2] }}</h6>
{% if session.username == comment[2] %}
<form action="{{ url_for('detail', slug=entry.slug) }}" class="form-horizontal" method="post">
<input class="form-control" name="commentid" type="hidden">
<div class="form-group">
<div class="col-sm-offset-0 col-sm-1">
<button class="btn btn-default1" type="submit">Delete!</button>
</div>
</div>
</form>
{% endif %}
<br></br>
{% endfor %}
When the button it pressed it should return the value of
{{ comment[3] }}
This value I should then be able to fetch from Flask in the form of
request.form.get('commentid')
Any ideas of how this could be done would be much appreciated!
<input class="form-control" name="commentid" type="hidden" value="{{ comment[3] }}">

Django/Bootstrap template rendering

I'm currently coding a website using Django and Bootstrap.
I created the templates and models first, and now, I'm implementing the controllers. All is not implemented yet, but I needed some help on this. I was wondering how to render a Django authentication form with the Boostrap grid system. I'm using Boostrap 4 and Django 2.0.4. My older form was like this :
<div class="jumbotron">
<form class="form-horizontal" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<div class="col-lg-4 offset-lg-4">
<label class="control-label" for="usernameInput">{{ form.username.label_tag }}</label>
<input id="usernameInput" type="text" name="{{ form.field.html_name }}" value="{{ form.username }}" class="form-control"
placeholder="Username">
</div>
</div>
<div class="form-group">
<div class="col-lg-4 offset-lg-4">
<label class="control-label" for="passwordInput">{{ form.password.label_tag }}</label>
<input id="passwordInput" type="password" name="{{ form.field.html_name }}" value="{{ form.field.value }}" class="form-control"
placeholder="Password">
</div>
</div>
<div class="container" id="btn_login">
<button type="submit" class="btn btn-primary btn-md" value="login" role="button">Log in</button>
<input type="hidden" name="next" value="{{ next }}"/>
</div>
</form>
<span class="container" id="forgotten_password">
Forgot your password ?
</span>
</div>
And here is the new one :
<div class="jumbotron">
{% load widget_tweaks %}
<form class="form-horizontal" method="post" action="{% url 'login' %}">
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
<div class="container" id="btn_login">
<button type="submit" class="btn btn-primary btn-md" role="button">Log in</button>
</div>
</form>
<span class="container" id="forgotten_password">
Forgot your password ?
</span>
</div>
But as you can obviously tell, this is not rendering the same way.
For example, I'd like to take back the width of the input.
For the rest, I use this line in my urls.py
re_path(r'^login/$', auth_views.login, {'template_name': 'main/login.html'}, name='login'),
And this one in my settings.py to get redirected to the right page :LOGIN_REDIRECT_URL = 'my_pls'
I googled a lot and finally used this link (in case you case notice something I didn't understand) : https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html#understanding-the-rendering-process
You should use custom HTML attributes on your **forms.py**.
It's simple:
from django import forms
class your_form(forms.Form):
attrs_for_the_field = {
'class': 'form-control',
'placeholder': 'Write here!',
}
field = forms.CharField(widget=forms.CharField(attrs=attrs_for_the_field))
With this code you will render the following HTML:
<input type="text" name="field" class="form-control" placeholder="Write here!" id="id_field">
Take a look at https://docs.djangoproject.com/en/2.0/ref/forms/widgets/ in order to know how Django represents an HTML input element.
You also should read https://docs.djangoproject.com/en/2.0/ref/forms/fields/ so that you could understand how it works.
You can add all the HTML configuration for the fields in the form code in forms.py . Than the form can be displayed with just {{ form.as_p}}.
Width of input can be retrieved with jQuery or JavaScript .

How can submit form with array fields and process on view?

I am trying to submit form with array fields and process on Django view. Also, I want to compare the submitted form data with correct answer table data.
question.html:
<form method="post" class="form-inline">
{% csrf_token %}
{% for question in questions %}
<h3>{{ question.title }}</h3>
<div class="radio">
<label class="radio-inline">
<input type="radio" name="ans{{ question.id }}" value="{{ question.option.0 }}">
{{ question.option.0 }}
</label>
</div>
<div class="radio">
<label class="radio-inline">
<input type="radio" name="ans{{ question.id }}" value="{{ question.option.1 }}">
{{ question.option.1 }}
</label>
</div>
<div class="radio">
<label class="radio-inline">
<input type="radio" name="ans{{ question.id }}" value="{{ question.option.2 }}">
{{ question.option.2 }}
</label>
</div>
{% endfor %}
<button type="submit" class="btn btn-success" name="ans_submit">Submit</button>
</form>
view.py:
if request.method == 'POST':
if(request.POST.get('ans_submit')):
temp_context["submitted_answers"] = request.POST.get("ans", "") # Receive as an array?
Expecting to get expert advice.
Thanks
Actually what is posted to you is ans0, ans1, ..., ansN.
So what you want to do is something like this:
answer_fields = [field for field in request.POST if field.startswith('ans')]
for field in answer_fields:
# Do something with `field`...
print(request.GET[field])
Additionally, you might want to check that the latter part is numeric, like so:
[field for field in request.POST
if field.startswith('ans') and field[3:].isnumeric()]

Submit without refresh - Django

i have a "follow" button on my web-site just like in Twitter. But this button is html-only without any js. I know nothing about js/jquery/ajax. Can anyone help me, what sholud i do to submit this form without page refresh? Thank you.
template 'event.html':
{% if user in event.users.all %}
<form action="/event/{{ event.id }}/" method="GET">
{% csrf_token %}
<input type="hidden" value="{{ event.id }}" name="remove">
<input type="submit" class="btn btn-warning btn-block" value="{% trans "Remove from My Events"%}">
</form>
{% else %}
<form action="/event/{{ event.id }}/" method="GET">
{% csrf_token %}
<input type="hidden" value="{{ event.id }}" name="add">
<input type="submit" class="btn btn-primary btn-block" value="{% trans "Add to My Events"%}">
</form>
{% endif %}
views.py:
def show_event(request, event_id):
event = get_object_or_404(Event, id=event_id)
user = request.user
if request.GET.get('add'):
event.users.add(user)
event.save()
if request.GET.get('remove'):
event.users.remove(user)
event.save()
return render(request, 'events/event.html', {'event':event, 'user':user}
First learn Javascript and Jquery and Ajax to understand more clearly.
http://www.tutorialspoint.com/jquery/
http://www.w3schools.com/jquery/
template 'event.html':
{% if user in event.users.all %}
<form action="/event/{{ event.id }}/" method="GET" id="event">
{% csrf_token %}
<input type="hidden" value="{{ event.id }}" name="remove">
<input type="submit" class="btn btn-warning btn-block" value="{% trans "Remove from My Events"%}">
</form>
{% else %}
<form action="/event/{{ event.id }}/" method="GET">
{% csrf_token %}
<input type="hidden" value="{{ event.id }}" name="add">
<input type="submit" class="btn btn-primary btn-block" value="{% trans "Add to My Events"%}">
</form>
{% endif %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.min.js"></script>
<script>
$('#event').submit(function(e){
e.preventDefault();
url = $(this).attr('action') # to get url
data = $(this).serialize(); # for sending form data
$.post(url, data, function(response){
# do whatever you want with response(data)
})
})
</script>
It is impossible, Python is a server side language and if you want to process data, you need send the information to the server.
The first time that i did this, i saw this video in YouTube: https://www.youtube.com/watch?v=KgnPSmrQrXI

Categories

Resources