Django unexpectedly splitting queryset objects on spaces - python

I'm having a problem where Django, or a form, is splitting object list items on spaces.
If the object_list is something like: ["picture"='image1.jpg "dir_as_title"='UnknownArtist', "picture"='image2.jpg' "dir_as_title"='Unknown Artist'] and I run it through the following:
<div>
{% for obj in object_list %}
<div class="col-md-6" style="background:url({{obj.picture}});
background-size: 100% 100%; min-height: 260px; max-width: 480px;" >
<form id="form" method="POST">
{% csrf_token %}
<input type="submit" value={{ obj.dir_as_title }}
name={{ obj.dir_as_title }} class="btn btn-primary btn-lg btn-block"/>
</form>
</div>
{% endfor %}
</div>
The first item will be fine, displaying 'UnknownArtist' in the button, and passing 'UnknownArtist' as its input. The second item will display the button as 'Unknown', and appears to pass no value, resubmitting its current state.

The answer ended up being embarrassingly simple. In other areas of the template, the double-brackets around a variable suffice, such as <h2>{{ title }}</h2> but in the form, they must be quoted. Using...
<input type="submit" value="{{ obj.dir_as_title }}"
name="{{ obj.dir_as_title }}" class="btn btn-primary btn-lg btn-block"/>
...works as expected, that is, it's no longer splitting the value. I hope this saves someone else from all the searches I did.

Related

Django multiple radio input from HTML form with same name

I am having a problem with Django forms. I am currently using the request.POST to validate the POST within views.
I want to send inputed-data(radio type) from my template with the same name.
In my template.py:
<form method="post" action="{% url 'app:AnsSubmission' %}">
{% csrf_token %}
{% for i in Exam %}
<div class="form-group col-xl-12">
<label>{{ i.question }}</label>
<div class="radio">
<label><input type="radio" class="mx-2" name="givenAns" array_column="{{ i.pk }} value="True" required>True</label>
</div>
<div class="radio">
<label><input type="radio" class="mx-2" name="givenAns" array_column="{{ i.pk }} value="False" required>False</label>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
And willing to fetch these data in views.py like:
givenAns_list = request.POST.getlist('givenAns')
for i in givenAns_list:
this_givenAns = givenAns_list[i]
But the problem here is this radio type input field doesn't take value for the same name(not as a list I wish). If I select answer of 2nd question, the 1st one's selection is unselected.
Please suggest how can I fix this?

Can't access an item in a dictionary that does in fact exist

I have two buttons on my page, each one in its own separate form.
One of the buttons, "deleteImage", works perfectly fine.
The other button, "search", won't work.
This is my response.POST when search is pressed.
request.POST <QueryDict: {'csrfmiddlewaretoken': ['randomtoken1234'], 'search': ['food', '']}>
request.POST.get("search") is failing to work for some reason, I tried printing it as well and nothing prints out.
my html
<form method="post" action="" class="form-group">
{% csrf_token %}
<div class="input-group mb-3">
{{form_search.search}}
<div class="input-group-append">
<button type="submit" class="btn btn-primary" name="search">Search!</button>
</div>
</div>
Looking at the QueryDict the key search is shown as 'search': ['food', '']. This means there are two values posted for search where one is an empty string.
I assume that this is because other than your button the form field for the search input is also named search. When one writes request.POST.get("search") they get the last value for the given key which here is an empty string for you (the value of the button).
The solutions are:
Change the name of the form field from search to something else.
Change the name of the submit button from search to something else. Which will be something like:
<form method="post" action="" class="form-group">
{% csrf_token %}
<div class="input-group mb-3">
{{form_search.search}}
<div class="input-group-append">
<!-- Change name attribute of button -->
<button type="submit" class="btn btn-primary" name="search-pressed">Search!</button>
</div>
</div>
</form>
Note that you might need to make some changes in your view as well to reflect these changes in the name.
Fixed by adding a value to the search button
<form method="post" action="" class="form-group">
{% csrf_token %}
<div class="input-group mb-3">
{{form_search.search}}
<div class="input-group-append">
<button type="submit" class="btn btn-primary" name="search" value="{{form_search.search}}">Search!</button>
</div>
</div>
</form>

Why request.method is not getting invoked?

I have a read-only textbox which preloaded value from database which upon a button click sends it's value to a method present in backend to perform DELETE query of sql. The problem is occuring when I am click on the button the method is invoked but the request.method condition is not invoked. It is directly going to the end return statement of the method.
#app.route('/home/delete_reminder/<string:id_val>',methods=['GET','POST'])
#is_logged_in
def delete_reminder(id_val):
if request.method=='POST':
desc = request.form['description']
x = desc.split(',')
cur = mysql.connection.cursor()
cur.execute('DELETE FROM set_reminder WHERE DATE=%s,SUBJECT=%s,DESCRIPTION=%s',[x[0],x[1],x[2]])
cur.execute('DELETE FROM recur WHERE RECUR_NEXT=%s',[id_val])
flash('Reminder Deleted','danger')
mysql.connection.commit()
cur.close()
return redirect(url_for('search_reminder_to_delete'))
This is my backend code.
<form method="POST">
{% for data in value %}
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
Delete Reminder
{% endfor %}
</form>
This is the html part.
Your button isn't a button, it's a link. You aren't submitting your form.
If you want to fo that then you need to make you form tag:
<form method="POST" action="/home/delete_reminder/{{data.RECUR_NEXT}}">
and switch your button to be a real button that submits the form:
<div class="button">
<button type="submit" class="btn btn-warning">Send your message</button>
</div>
EDIT: Seeing that you want to have multiple possible routes for your form based on the loop.
You could try and use the formaction attribute, although it isn't going to be supported by every browser version.
<form method="POST">
{% for data in value %}
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
<div class="button">
<button formaction="/home/delete_reminder/{{data.RECUR_NEXT}}" class="btn btn-warning" type="submit" class="btn btn-warning">Delete Reminder</button>
</div>
{% endfor %}
However this will still result in your description field that is passed to the request having every single description from the whole form in a list or possibly just the last one as a single value (I can't quite remember the behaviour of multiple inputs with the same name), which I don't think is what you're expecting to happen.
It may just be easiest to create a separate form for each link in a loop to be honest:
{% for data in value %}
<form method="POST" action="/home/delete_reminder/{{data.RECUR_NEXT}}">
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
<div class="button">
<button class="btn btn-warning" type="submit" class="btn btn-warning">Delete Reminder</button>
</div>
</form>
{% endfor %}

disable validation in back button in django form

I have a form representing a quiz with some questions and a result that appears in the end in Django 1.10. I need t implement two other buttons next to the "Check" button, one of them is "Mark" and the other is "Back".
When I click on "back", I m handling well its behavior in the view but a pop up appears saying "Please Select One Of these Options".
I need to disable it since user should not select one of the radio buttons if going back to the previous question.
<form action="" method="POST">
{% csrf_token %}
<input type=hidden name="question_id" value="{{ question.id }}">
<ul class="list-group">
{% for answer in form.answers %}
<li class="list-group-item" >{{ answer }}</li>
{% endfor %}
</ul>
<div id="buttons">
<input type="submit" name="question_btn" value={% trans "Check" %} class="btn btn-lg center-block btn-outline btn-success" required>
<input type="submit" name="question_btn" value={% trans "Back" %}
class="btn btn-lg center-block btn-outline btn-success" required>
Any idea?
The back button shouldn't be an input and a type="submit". Just make it a button or a a element and that would work nicely.

How to get the data from HTML field to the view.py in django(HTML field is iterating)

I have an app which reads the questions from database and display them .I need to enter the response to it and save it back in the database.Is it possible to do it without using forms
My HTML section
<form id="survey" method="post" action="/Survey/restricted/" class="form col-md-12 center-block">
{% csrf_token %}
{% for b in obj1 %}
<textarea class="form-control">{{b.question}}</textarea>
<textarea class="form-control" rows="3" name="response1" width="100%;">{{b.response}}</textarea>
{% endfor %}
<input type="submit" name="submit" class="btn btn-success" value="Submit Response" />
</form>
I tried to access the data after entering the response and submitting using
res=request.POST.get('response1')
but it returns none
You should move the response1 field outside the loop, but then it should be passed as a separate field (e.g. response), not as part of the obj1 list of questions (or not passed at all if keeping the previous answer is unnecessary).
<form id="survey" method="post" action="/Survey/restricted/" class="form col-md-12 center-block">
{% csrf_token %}
{% for b in obj1 %}
<textarea class="form-control">{{b.question}}</textarea>
{% endfor %}
<textarea class="form-control" rows="3" name="response1" width="100%;">{{response}}</textarea>
<input type="submit" name="submit" class="btn btn-success" value="Submit Response" />
</form>
Also, I think the questions should not be editable (i.e. disabled, or not a textarea altogether)

Categories