How to access custom session attribute in template - django

I fail to access a value that I stored in the session:
views.py
...
request.session['content_lang_code'] = request.GET.get('lang')
base.html template
</body>
<p>Hello {{ request.user.username }} your selected content language is:
session.content_language_code {{ session.content_language_code }} <br>
request.session.content_language_code {{ request.session.content_language_code }}
</p>
While the username is rendered, content_language_code is not. The debugger shows that content_language_code is in session._session. I tried session.get('content_language_code') as well, but that did no work either.
What is the correct way to retrieve a session attribute from within a template?
(debug screen shot at http://lcrfiles.hoerbe.at/stuff/screenshot2013-03-29.png)

You put it in the session with the key content_lang_code but are trying to access it with a different key content_language_code. If you change {{ request.session.content_language_code }} to {{ request.session.content_lang_code }} it should work.

Related

Javascript returns the same id for every iterated element in html

I have website which i build using Django where every visitor can leave their message or press a like button on any comment. I would like to show how many of a comment has been liked by the user.
As each comment is unique, I think to access the comment_id attribute which I wrote in the html part. I then use a simple js function to retrieve the id. The problem is, although html is showing unique id for each comment, Javascript still return the same id, that is the id of the first comment that is written on the page. Can someone tell me where is my mistake in this case?
Thank you in advance for your help.
my code in js:
function likeButton(){ let el = document.getElementById("chat-icon-thumbsup") alert(el.attributes["comment_id"].value) };
my html code, which is looping the datatable records "comment" from a datatable in Django framework:
{% for comment_ in comments %} <strong> {{ comment_.name }} - {{ comment_.date_added }} <button><i comment_id="{{ comment_.comment_id }}" id="chat-icon-thumbsup" class="fa fa-fw fa-thumbs-up" title="like this comment" onclick="likeButton()"></i></button> {{ comment_.nr_of_likes }} <br/> </strong> {{ comment_.body }} <br/> {% endfor %}
image 1: here you see when I inspect the DOM elements, it retrieves different "comment_id"
enter image description here
image 2 and image 3: every button pressed in the comment line alerting the same id, which is 16
enter image description here
I tried to google any possible same problem, but no solutions found
In HTML an ID should be unique on every page. JS will therefore only return the first field it finds with that ID. What you should be using is a class-name that defines your field, like this for example:
<i id="comment_{{ comment_.comment_id }}" class="fa fa-fw fa-thumbs-up chat-icon-thumbsup" ....>
Then you can use document.getElementsByClassName("chat-icon-thumbsup"), there is a reason why it's called getElementById as singular and not getElementsById

How to render clear checkbox manually in Django Forms?

In Django when dealing with an image in a form, there is always this clear checkbox (if the image is nullable), e.g.:
<input type="checkbox" name="image_var-clear" id="image_var-clear_id">
<label for="image_var-clear_id">Clear</label>
Now, I wish to render it manually. If I place "{{ form.image_var }}" in my HTML, the checkbox appears and the above html code is generated, but I cannot figure out how to render it completely manually. So far I managed to get these values:
if required: {{ form.image_var.field.required }}
checkbox label: {{ form.image_var.field.widget.clear_checkbox_label }}
input text: {{ form.image_var.field.widget.input_text }}
checkbox name: {{ form.image_var.field.widget.name }}
text: {{ form.image_var.field.widget.initial_text }}
This all works fine, until I want to render the checkbox_id with:
{{ form.image_var.field.widget.checkbox_id }}
What am I missing?

.Site.Data values are not accessible inside a range block

So I just noticed that when I try to access something from .Site itself inside a range block it returns as null/blank.
Here's an example:
<div class="row weekday">
{{ .Site.Data.company.social_media.whatsapp }}
{{ range $entry := sort .Site.Data.events "order" "asc" }}
<div class="col-sm-6 col-md-4 col-lg-4">
{{ .Site.Data.company.social_media.whatsapp }}
{{ partial "events_detail.html" (dict "entry" $entry) }}
</div>
{{ end }}
</div>
The first .Site.Data.company.social_media.whatsapp (before the range) renders a phone number.
The second .Site.Data.company.social_media.whatsapp (after the range) do not renders anything.
This same behavior happens in the partial events_detail.html. If I try to access the .Site from inside of the partial scope it renders a null. I also tried to pass it along on the (dict ...) but no lucky.
What Am I missing here?
I was missing how Hugo manage the scopes for the dot. You read a more in-depth explanation about this (and other important concepts) here:
https://regisphilibert.com/blog/2018/02/hugo-the-scope-the-context-and-the-dot/
In Resume is (extracted from the link above):
The root context, the one available to you in your
baseof.html and layouts will always be the Page context. Basically
everything you need to build this page is in that dot. .Title,
.Permalink, .Resources, you name it.
Even your site’s informations is stored in the page context with .Site
ready for the taking.
But in Go Template the minute you step into a function you lose that
context as your precious dot or context is replaced by the function’s
own… dot.
(...)
Same goes here, once you’ve opened an iteration with range the context
is the whatever item the cursor is pointing to at the moment. You will
lose your page context in favor of the the range context.
{{ range .Data.Pages }}
{{/* Here the dot is that one page 'at cursor'. */}}
{{ .Permalink }}
{{ end }}
Luckily Hugo stores the root context of a template file in a $ so no
matter how deeply nested you are within with or range, you can always
retrieve the top context. In basic template file, it will generally be
your page.
{{ with .Title }}
{{/* Dot is .Title */}}
<h1>{{ . }}</h1>
{{/* $ is the top level page */}}
<h3>From {{ $.Title }}</h3>
{{ end }}

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.

Django not displaying images from blog Post

I have created a DJANGO blog-engine which takes my post and the template parses it for html tags. links etc.. are working but it does not load image file and instead shows the 'alternative' . I have tried the tag in separate html files and it is otherwise. Just not displaying image from inside a django blog post.
Relevant portions of the template file :
{% include 'blog/header.html' %}
</aside>
<section id ="content">
<article>
{%for post in posts %}
<h2>{{ post.title }}</h2>
<h3>{{ post.created}}</h3>
<p>
{{ post.body|safe }}<br>
</p>
<h3>By {{ post.author }}</h3>
I am copy-pasting the post in question
<---- text here ------------------>
GDCM::Directory
<img src="/home/usman/www/deejay/blog/static/images/dicomdir.png" />
This is it
Interestingly, the 'a' tag works fine but the 'img' tag is not working. I have tried many variations but i want some inline code to display simple html tag, alternatively of course i will resort to it programmatically by passing some variable to the template from inside the post to let it know where to position the image.
Your problem is here: {{ post_get_absolute_url }}. You should use {{ post.get_absolute_url }}.
The better way is to call the URL of the image directly; that way you maintain your URLs in urls.py and not in your model code. It makes your app more portable.
Take your image field name value from your model, and then {{ post.image.url }}. For example, if your model is:
class Post(models.Model):
img = models.ImageField(upload_to='images')
Then you would use {{ post.img.url }}
Problem solved when I replaced the full address with
<img src="/static/images/dicomdir.png"/>
On development server as well as on production. What helped was that I looked at the Dev-server responses on my terminal and was able to figure out the url.