unable to render objects to html - no error messages - django-rest-framework

I am trying to render some object data from view - > html. I've managed this for other Django projects, and I am a bit lost why the following is not working. Help is much appreciated!
I am receiving no error in the http response and from as far as i can tell the below should work.. The same objects are displayed in the backend without issue, see last code snippet for that view.
Solved
Typo - below in the html
{% 'for val in context'%}
did not receive the input from views as it was called context: in the render
{'context:' : objects}
Thanks all
My html:
<div id="home_top_left_inner" class="container-fluid">
{% if user.is_authenticated %}
{% for val in context %}
<p class='white_text'>{{ val }}</p>
{% endfor %}
{% endif %}
</div>
Views
from api.models import general_employee_data
def index(request):
all_employees = general_employee_data.objects.all()
return render(request, 'index.html', {'context' : all_employees})
If I put a print in the above view I receive
<QuerySet [<general_employee_data: chang, ko-lin - portal id: ki5s0r3ab>,
<general_employee_data:
test, test - portal id: 19eohz4gy>]>

<p class='white_text'>{{ val }}</p>
remove class='white_text'
If the background is white, do not use the white text colour.

Related

Django messages not displaying on webpage

I created and imported the usual "django.contrib" from message, attached is the code snippet for my view.py page and register.html.When I tried to register a new user, I"m not getting the warning message on the webpage instead all I get is "<django.contrib.messages.storage.fallback.FallbackStorage object at 0x00000230B847FEE0>" i don't know what am doing wrong. Please help Thanks in advance.enter image description here
messages in django is a class , for display messages you need to iterate on it
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
django docs

How to set each field as required for formset_factory in Django (how to validate blank forms in formsets)

I have the form in my forms.py:
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
age = forms.CharField(label='Age', max_length=100)
sex = forms.CharField(label='Sex', max_length=100)
I created the formset_factory
NameFormSet = formset_factory(NameForm, extra=0)
In my views.py for the get context_data, I have:
...
def get_context_data(self, **kwargs):
context = super(APView, self).get_context_data(**kwargs)
if self.request.POST:
context['formset'] = NameFormSet()
else:
recommended = returnWebAttackResults(self.kwargs['webAttack'])
if recommended is None:
context['recommendedAP'] = False
else:
context['formset'] = NameFormSet(initial=recommended[0])
return context
....
In my template file, I have:
<form class="row" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
{% for forma in formset.forms %}
{{ forma }}
{% endfor %}
<input class="btn bg-success" type="submit" value="Update" />
</form>
My problem is that I don't get "This field is required" when I click the "Update" button. I tried setting the use_required_attribute to True, but it did not work.
Scenario:
The returnWebAttackResults function gets the initial data for the forms in the formset. So, if I have three forms, if one of the fields is blank (no user input) in any of the forms, then when I click the Update button, each field that is blank should be highlighted with the "This field is required". I can do this when I just render a regular form, but when I am using formsets, it does not work.
Is there a way to validate the forms in the formset before the request in sent?
I hit the same problem and found this in the documentation
https://docs.djangoproject.com/en/3.0/ref/forms/fields/#core-field-arguments
Widgets of required form fields have the required HTML attribute. Set the Form.use_required_attribute attribute to False to disable it. The required attribute isn’t included on forms of formsets because the browser validation may not be correct when adding and deleting formsets.
If you have an empty row (for adding an extra record) then you can't save the form until the empty row is filled in. So, if you want to say update one existing row without adding an extra row then you have a problem, you can't do it. The problem really comes from the fact that a formset is really in html terms just a single form. A workaround for that problem might be to use javascript to add rows to the formset only as needed, as in this example:
https://whoisnicoleharris.com/2015/01/06/implementing-django-formsets.html
There is probably furthermore a javascript solution to validate the form fields before you send the request, I think this may be such a solution but I haven't tried it:
https://jqueryvalidation.org/required-method/
It would make sense that a completely empty row should not be validated for required fields but just ignored altogether.
UPDATE: I got a simple solution working from the example in the above link. My template looks like this (note that no empty row is shown initially thanks to the if statement):
{% extends "base_generic.html" %}
{% load static %}
{% block content %}
<h1>Experiment Detail</h1>
<form name="test_form" method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{% if form.name.value %}
<div class="link-formset">
{{ form.name }}
</div>
{% endif %}
{% endfor %}
<input type="submit" value="Save" class="button"/>
</form>
<!-- Include formset plugin - including jQuery dependency -->
<!-- <script src="{% static 'path_to/jquery-3.4.1.js' %}"></script> -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'js/jquery_formset.js' %}"></script>
<script>
$('.link-formset').formset({
addText: 'Add',
deleteText: 'Delete'
});
</script>
{% endblock %}
In my view I have this for loop to set the use_required_attribute:
for form in formSet:
form.use_required_attribute = True
The solution seems to work OK, when I click the Add button an empty row appears and the empty 'name' field has the expected red box round the empty field and when I try to click Save I get the message 'Please fill out this field.'
the solution is, add BaseFormSet in froms.py, like this:
forms.py
from django.form import BaseFormSet
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100, blank=False)
age = forms.CharField(label='Age', max_length=100, blank=False)
sex = forms.CharField(label='Sex', max_length=100, blank=False)
class RequiredFormSet(BaseFormSet):
def __init__(self, *args, **kwargs):
super(RequiredFormSet, self).__init__(*args, **kwargs)
for form in self.forms:
form.empty_permitted = False
form.use_required_attribute = True
NameFormSet = formset_factory(NameForm, formset=RequiredFormSet)

How to display data from Jekyll data file based on current page variable

The Problem
I have a div on my Jekyll site where I would like to display data that is generated from _data/book-data.yml, for example:
- name: johnson-everything-under
title: Everything Under
author: Daisy Johnson
publisher: Faber & Faber
pub-date: 12/12/2012
- name: johnson-train-dreams
title: Train Dreams
author: Denis Johsnon
publisher: Granta
pub-date: 01/01/2001
I'm trying to find a way to display the data that corresponds to the relevant page (each book entry has a different page), and I thought maybe this would be possible if the name key corresponds to the page.url, or some other page variable.
What I've tried
On a working page, I have an include which contains the following HTML:
<div class="book-meta">
{% if page.category == "reviews"%}
<div class="book-thumbnail">
<img class="post-thumbnail-lg" src="{{ site.baseurl }}/assets/images/{{ page.thumbnail }}" alt="{{ page.thumbnail }}">
</div>
{% for book in site.data.book-data %}
<div class="book-details">
<ul class="book-meta-list">
<li class="book-meta-item"><p>{{ book.author }}</p></li>
<li class="book-meta-item"><p><em>{{ book.title }}</em></p></li>
<li class="book-meta-item"><p>{{ book.publisher }}</p></li>
<li class="book-meta-item"><p>{{ book.pub-date }}</p></li>
</ul>
</div>
{% endfor %}
{% endif %}
</div>
The CSS is not important, but as it is currently the output of the above HTML is:
Desired output
As you can see, the output contains both the blocks of metadata from the .yml file. I would like to find a way so that only the relevant block of data (the first block in this instance) is displayed:
Potential solution(s)
I thought that there might be a way of matching a page.variable to the YAML block name so only the right book data gets output. Something along the lines of:
{% assign url_substring = page.url | split, '/' | last %}
// url_substring = johnson-everything-under
{% for book in site.data.book-data %}
{% if url_substring == book.name %}
// = true
<p>{{ book.title }}<p>
{% endif %}
{% endfor %}
Other than the fact that I can't get this to work properly, I can also see that the liquid tag {{ book.title }} has no way of knowing which book title to output, even if the page.url matches.
I'm not sure if I'm on the right track here, so if anyone has any other suggestions on how this might be achievable, I'd love to hear it. Thanks in advance.
You can use Jekyll's where filter coupled with a smart include:
{% assign book = site.data.book-data | where: 'title', include.title | first %}
<div class="book-meta">
<div class="book-thumbnail">
<img
class="post-thumbnail-lg"
src="{{ book.thumbnail | prepend: 'assets/images/' | relative_url }}"
alt="{{ book.title }}"
/>
</div>
<div class="book-details">
<ul class="book-meta-list">
<li class="book-meta-item"><p>{{ book.author }}</p></li>
<li class="book-meta-item"><p><em>{{ book.title }}</em></p></li>
<li class="book-meta-item"><p>{{ book.publisher }}</p></li>
<li class="book-meta-item"><p>{{ book.pub-date }}</p></li>
</ul>
</div>
</div>
Note that I also included thumbnail info in the data file..
Then just pass the title parameter to the include (in the layout for your book's page):
{% include books.html title = 'Everything Under' %}
If you'd like to render a "listing", then just loop through and render:
{% for book in site.data.book-data %}
{% include books.html title = book.title %}
{% endfor %}

Deletion by tab button doesn't work

Several DEVICE forms can be displayed on a page (Order), as tabs. When a user closes a tab and hits save, then renters that particular Order (ID), the user still sees his deleted tab. As a quick workaround, a checkbox was built into the html code but this is not desired.
Currently the code in my view.py looks like this.
def edit_order(request,id = None, order_id = None):
order = Order.objects.get(id=id)
'''some stuff'''
if request.method == 'POST':
formCustomer = CustomerModelForm(request.POST,instance=Customer.objects.get(order=order.id))
formInfo = InfoModelForm(request.POST,instance=Info.objects.get(order=order.id))
DBFormSet = modelformset_factory(DB, extra=1, can_delete=True, form=LUNModelForm)
formset = DBFormSet(request.POST or None, queryset=DB)
if formset.is_valid():
for i,frm in enumerate(formset.forms):
if frm.cleaned_data['id']:
if frm.is_valid():
if not frm.cleaned_data['capacityGB'] > 0:
frm.cleaned_data['id'].delete()
elif frm.cleaned_data['DELETE'] == True:
frm.cleaned_data['id'].delete()
#frm.save() or formset.save() ??
else:
dev = frm.cleaned_data['id']
dev.capacity = frm.cleaned_data['capacity']
dev.save()
I suspected the matter that the tab was not remaining closed was an issue with "can_delete", but it doesn't seem to make a difference when I added this. Then I read that the issue could be related to the formset.save, which also didn't resolve anything. Below the html code:
html:
<ul class="nav nav-tabs" id="tab4Headers">
{% for form in formsetDEVICE.forms %}
{% if forloop.first %}
{% if form.errors %}
<li class="active">DEVICE <i class="icon-warning-sign"></i> </li> <!-- section 4.1 -->
{% else %}
<li class="active">DEVICE</li> <!-- section 4.1 -->
{% endif %}
{% else %}
{% if form.errors %}
<li><button class="close" type="button" id="close-tab4_{{forloop.counter}}">×</button>DEVICE <i class="icon-warning-sign"></i> </i></li> <!-- section 4.2 ... 4.n -->
<!--{% if formsetDEVICE.can_delete %}
<li>{{ form.DELETE }}</li>
{% endif %}-->
{% else %}
<li><button class="close" type="button" id="close-tab4_{{forloop.counter}}">×</button>DEVICE</li> <!-- section 4.2 ... 4.n -->
<!--{% if formsetDEVICE.can_delete %}
<li>{{ form.DELETE }}</li>
{% endif %}-->
{% endif %}
{% endif %}
{% endfor %}
</ul>
Since it is not clear how to delete the tab via closing the tab (and then hit the save button), the current work around is simply to insert a section on the tab with a checkbox included, as so:
{# --- delete item --- #}
{% if form.instance.pk %}
{# render row for DELETE-flag only for forms with existing instance #}
<tr>
<td colspan="2">
</td>
<td colspan="2">
edit Action required: <br/><br/>
{{form.DELETE|safe}} delete this DEVICE from the Order.
</td>
</tr>
{% endif %}
{# --- END delete item --- #}
The current workaround works, but this is not the desired functionality. I've tried some of the suggestions as seen here, but to no avail. I think the problem is more related to the link between the html and the view.py (so something to do with frm.cleaned_data['DELETE'] though I could be wrong.
EDIT:
I suspect to get around this, js code and/or css needs to be inserted.
I was having the same problem with inlineformset_factory. Reading the base Django classes, i found the problem seems to be in BaseFormSet class (or some like that), the _should_delete_form() method looks for the forms DELETE value in cleaned_data, but using debugging i found that the DELETE value doesn't exist in cleaned_data, neither the DELETE field exists by the time cleaned_data is populated.
I think this could be because the DELETE field is dynamically created by FormSet Classes, but cleaned_data is populated by the Form class before the DELETE field is created (somewhere on forms init? maybe) so as this field doesn't exists, cleaned_data DELETE value isn't populated.
Somewhere in the base FormSet classes, the dynamically created DELETE field value have to be included in cleaned_data, BUT i found a quick and temporary solution to this, Add the DELETE field to the form class:
class RutinaForm(ModelForm):
DELETE = forms.BooleanField(required=False, widget=forms.CheckboxInput())
class Meta:
model = Rutina
fields = '__all__'
exclude = ('usuario',)
widgets = { .........}
This way the DELETE field exists so its value gets cleaned and added to cleaned_data.
This can be seen like a "machetazo", but it works! at least temporary. I will continue reading the base code and look if it is a bug, or what is happening.
Note: Sorry for my english, and i'm not an expert so PLEASE give me your comments.
This is my view if you need it, or if you can find what is wrong:
rutinaFormSet = inlineformset_factory(Usuario, Rutina, form=RutinaForm, can_delete=True, extra=1)
if request.method == 'POST':
formSet = rutinaFormSet(request.POST, instance=usuario)
if formSet.is_valid():
formSet.save()
else:
formSet = rutinaFormSet(instance=usuario)

Create Jekyll link from YAML array

I have a YAML array in a file called navigation.yml as follows:
docs:
- title: Home
url: index.md
id: index
- title: Support
url: support.html
id: support
- title: About
url: about.md
id: about
I am creating a navigation bar as follows:
<section id="navigation" class="clearfix">
{% for item in site.data.navigation.docs %}
<span>{{ item.title }}</span>
{% endfor %}
</section>
What should I put in place of index.md to get the item.url that I want from the YAML file.
I am totally new to GitHub Pages, YAML, and Jekyll.
At the moment, the link tag doesn't seem to support variables.
There's a pull request trying to change this, but it has not been merged into the main Jekyll repo yet.
So if you want to do this now, you need to use some tricks.
The solution suggested by flyx in his comment (replace {% link index.md %} by {{ item.url }}) basically works, but shows the original filename written in the data file.
⇒ If index.md is automatically renamed to index.html while rendering the site, your link won't work anymore.
(or if support.html becomes support/index.html)
That's probably why you wanted to use the link tag instead.
Without using the link tag, you need to loop your data file, loop through all pages to find the respective page, and show that page's actual URL in your link:
<section id="navigation" class="clearfix">
{% for item in site.data.navigation.docs %}
{% for page in site.pages %}
{% if page.path == item.url %}
<span>{{ item.title }}</span>
{% endif %}
{% endfor %}
{% endfor %}
</section>
This even takes stuff like explicitly set permalinks (permalink: /whatever/ in the page's front matter) into account.

Resources