Flask keeping checkboxes after page regresh - flask

I have this piece of code of a flask template
<div class="rows">
<h3>In oven</h3>
{% for checkbox in checkboxes: %}
<li><input type="checkbox"></li>
{% endfor %}
</div>
I tried using java script but after refresh the checkboxes resets even if I checked it before. I want to checked it and after refreshing the page the check to stay. Any ideas how to do it?

You need to store somewhere the value of the checkbox to set it when loading the page again.
Local storage
Flask session
Database
Ajax query
With a form
This value has to be something that can be evaluated as true/false.
After retrieving the value you need to evaluate for add or not the checked property in the input.
In this example, I'm using a variable on the view.
#app.py
#app.route("/")
def sample():
your_variable=True
return render_template('index.html', your_variable=your_variable)
#index.html
<div class="rows">
<h3>In oven</h3>
{% for checkbox in checkboxes: %}
<li><input type="checkbox" {{'checked="checked"' if your_variable else ""}}></li>
{% endfor %}
</div>
Of course, with a more complete question this can be more specific

Related

External URL into a iframe to embed an external url within Django

I would like to embed a pptx that is uploaded into a folder in OneDrive within a iframe tag in a Django template. I have the urls stored in a model and saved into the SQLite database. In this sense, in the views.py file, I have the following code:
context = {
'selectedunit': selectedunit,
'url_to_be_inserted': MyModel.objects.filter(unit=selectedunit)
}
return render(request, 'web.html', context)
The code for web.html is very easy:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="container col-lg-8">
<div class="center">
<iframe class="center" src={{ url_to_be_inserted.url }} width="100%" height="300%" frameborder="0"/>
</div>
</div>
{% endblock %}
The result is the snapshot below:
While, I would like to embed the ppt into the web site. If I directly insert the URL, instead of using the context variable, it works. That is to say:
<iframe class="center" src="https://..." width="100%" height="300%" frameborder="0"/>
In this case, the result is as follows (ppt embedded into the Web site):
The reason why doing in this sense is because, depending on the selectedunit variable, I would like to address a different pptx with a different URL and I would like to dynamically change the pointer (as you see above by filtering the model).
How could I solve it?
Many thanks in advance

How to pass a <select> in a View using Django

I was trying to make a cart system in Django and wanted to pass Size and the Quantity of product as <Select>
input in View.
My Template have :
<ul class="list-unstyled">
Select Size:
<select name="sizes">
{% for size in product.sizes.all %}
<li class="list-item list-inline-item"><option value="{{size.nameSize}}">{{size.nameSize}}</option> </li>
{% endfor %}
</select>
</ul>
This is how it looks :
But when i Submit it using the Add to Cart Button i get error:
This is the code in the view:
def add_item(request,pk):
product = get_object_or_404(Product,pk=pk)
size = request.POST['sizes']
selectsize = Size.objects.get(nameSize=size)
user = request.user
usercart = Cart.objects.get(owner=user)
newitem = CartItems.objects.create(cart = usercart,product=product,size=selectsize)
items = usercart.cartitems
return render(request,'cart.html',{'cartitems':items})
I am trying to use the name of the size from the Template and compare the size name i have in the database for that product Using:
selectsize = Size.objects.get(nameSize=size)
I was able to get size with name 36 so i wanted to pass the value 36 from the template to the variable size using post.
But i get the error mentioned which i believe is because name for the <select> is common in all the <option>.
If i can either get an alternate way to do that or solve this error both type of solutions are welcomed.
*I am not using Django Forms because i don't know how to have django form display like i am displaying my products in cart and on the product page.
ANSWER
I was missing a submit button and was rather using a <a href="{% url 'add_item' product.pk %}>Add To Cart</a>" to submit the form which was not working.
Now i replaced it with <button class="btn btn-success" style="margin-top: 10px;" type="submit">Add To Cart New</button>
And the form Action is given the link i was trying to go to.
<form method="post" enctype="multipart/form-data" action="{% url 'add_item' product.pk %}">
A silly mistake on my side.
Thanks for the answers.
Expanding on what #Yevhenii M. said, and talking particularly about the MultiValueDictKeyError:
This error happens when the given key (sizes in this case) is not found in the POST dict. This might be happening (i'm only guessing, since you didn't post the full html code), because you didn't put the corresponding <form> tag surrounding the select.
So, the final code would look something like:
<form action="url-to-send-form-data" method="POST">
{% csrf_token %}
<select name="sizes">
{% for size in product.sizes.all %}
<option value="{{size.nameSize}}">{{size.nameSize}}</option>
{% endfor %}
</select>
</form>
The {% csrf_token %} is needed in order to protect you against Cross Site Request Forgery attacks (more info: https://docs.djangoproject.com/en/2.2/ref/csrf/)
EDIT: Now that I take a closer look, the error message shows that the url is being called with a GET request (maybe because of trying to access to /item_added/1 straight from the browser's url). That is why django can't find the sizes key.
One common way to call the url via post, is as shown in the code snipet above, and adding a submit button to the html:
...
<button type="submit">Submit</button>
</form>
You don't need to use <ul> tag here.
You can write:
Select Size:
<select name="sizes">
{% for size in product.sizes.all %}
<option value="{{size.nameSize}}">{{size.nameSize}}</option>
{% endfor %}
</select>
and result will be the same.
Since you didn't specify that add_item(request, pk) works only by POST, then you can't expect that request.POST always will be presented.
Better write your code as this:
if request.POST:
# do something
And if you don't specify default value for your select in template, then sizeswill not be in your request.POST.
You can write like this just to be sure that you got some value:
request.POST.get('sizes', 'some_default_value')
Just because you get MultiValueDictKeyError you need to see what you get in request. Maybe you get QueryDict, then you need to extract first value. For example, see this SO question. For example, print your request.POST or check type.

Add button against each record on django admin change list page?

I want to add a button against each row on django admin change list page. When that button is clicked, i want to make entries in some database table(all this happens on the backend) and after that the button should be disabled on the same page against that row.
How can i achieve this? I have searched a lot button there is no solution available.
You are going to have to edit the changelist_result_list template at the point where the result items are generated (near the bottom) to add an element that provokes a request. For example:
<tr class="{% cycle 'row1' 'row2' %}">
{% for item in result %}
{{ item }}
<!-- NEW STUFF --->
{% if forloop.last %}
<td>{% if pk %}CLICK ME{% endif %}</td>
{% endif%}
{% endfor %}
</tr>
(Don't forget to also update the table headers further up)
You are going to have to provide a template context variable for {{pk}} by messing with the templatetag result_list in django.contrib.admin.template_tags.admin_list -- meaning, you are creating your own templatetag for this.
Then you need to set up a view and an url conf to handle the request the links send.
Let's say you're at foo/bar and click on the link for the row with pk=2. A GET request will be send for foo/bar/do_things_with_object_2.
Your url conf needs to capture the pk (and the model, here: bar) and your view needs to do whatever it is you want on the object.

Display Form Field based on other Fields within the Django Form

I am trying to create a way to only display certain fields within a django form based on the bound data of another field within that same form. I'm familiar with the idea of form.field.bound_type but I'm not sure how to continually check for state change on a field in a form and update the other field accordingly. Something like if you were filling out an application and it asked if you've committed a crime, if you click yes then a details text area pops up.
I'm using:
Django 1.8.4
Bootstrap3 6.6.2
As it pertains to this question. Here is what I've currently got with the field values edited for work protection. It does SORT of work. Meaning the form is fine, the if statement works initially but it doesn't reevaluate the if once the specified field has changed.
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
{% bootstrap_field form.field_three%}
{% if form.field_three.bound_data == "A Value" %}
{% bootstrap_field form.field_four%}
{% endif %}
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>
Solution:
With Birdie's help I was able to figure out the solution. For anyone who has hit this same Django related problem here is how you add or remove fields based on another field in the same form.
<script>
// function that hides/shows field_four based upon field_three value
function check_field_value(new_val) {
if(new_val != 'A value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#field_four').removeClass('hidden');
} else {
$('#field_four').addClass('hidden');
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#field_three').change( function() {
check_field_value(this.value);
});
});
</script>
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
<div id="field_three">{% bootstrap_field form.field_three%}</div>
<div id="field_four">{% bootstrap_field form.additional_notes %}</div>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>
You cannot do this within the template because the template is executed on the server side, but the user interaction occurs on the client side.. in the browser. This must be done in javascript and run in the browser.
Here is an example of jQuery code which does this. I did not test it so it may need tweaking, but this should get you in the right direction.
You will need to look at your HTML to determine the id of the element you actually want to hide() and show(). Normally you would have some kind of HTML element (eg. a DIV) surrounding both the field or fields you want to hide as well as the label(s).. and you would hide everything at once by hiding the element which contains all the fields, rather than each individual field itself.
If you add the HTML surrounding field_four to your question, I will update the answer to work with what you've got...
<script>
// Ideally this script (javascript code) would be in the HEAD of your page
// but if you put it at the bottom of the body (bottom of your template) that should be ok too.
// Also you need jQuery loaded but since you are using bootstrap that should
// be taken care of. If not, you will have to deal with that.
// function that hides/shows field_four based upon field_three value
function check_field_value() {
if($(this).val() == 'A Value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#id_field_four').hide();
} else {
$('#id_field_four').show();
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#id_field_three').change(check_field_value);
// set the state based on the initial values
check_field_value.call($('#id_field_three').get(0));
});
</script>
Thanks all for the contribution, but I could not get the code above work. This is my solution:
<script>
function hideField() {
check = document.getElementsByName("put your field name here")[0].value;
response = document.getElementById("put your id here");
if (check === "Open") {
response.style.display = "none";
}else{
response.style.display = "block";
}
}
</script>
The key is to figure out Id for the field you want to hide, and name for the field you check. I did NOT use DIV container to assign the id and the name, but inspected rendered HTML page with developer tools in the browser. Let me know if you have questions or want more detailed explanation.
I found this question very interesting. I have updated it with bootstrap 4.0v, with the following script, I hope it can help someone:
<script>
// function that hides/shows field_four based upon field_three value
function check_field_value(new_val) {
if(new_val != 'A value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#field_four').removeClass('d-none');
} else {
$('#field_four').addClass('d-none');
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#field_three').change( function() {
check_field_value(this.value);
});
});
</script>
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
<div id="field_three">{% bootstrap_field form.field_three%}</div>
<div id="field_four">{% bootstrap_field form.additional_notes %}</div>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>

Django Caching - Not caching for certain part of the page

I have a problem with django caching for login area using Safari.
When I use memcache and have 'django.middleware.cache.FetchFromCacheMiddleware' on, the login part of the page is always cached, showing "Welcome username" even after I press Logout.
It should change back to "login/sign up" link after logout is clicked. This seems to happen only in safari. Is there any way to not cache a part of the HTML page? I used #never_cache when it comes to view functions, but this login information is part of the base.html which gets extended throughout other site template htmls.
Thank you.
Code
In base.html
{% if user.is_authenticated %}
<div class="login">
<a id="login_dropdown_link" title="Login_nav">Welcome {{ user.username }} ( <span id="total_count"> {% total_count %}</span> )</a>
</div>
{% else %}
<div class="login">
<span class="spaced">Log In | Sign Up</span>
</div>
{% endif %}
This is most likely due to a header issue where Safari is being instructed to cache the page for a certain amount of time.