Django Datatables view - django

Im trying to convert my tables in my django app to datatables using django-tables2.
Im my campaigns.py view I have:
class CampaignListView(FacebookAdInit):
""" CampaignListView for viewing all the campaigns"""
def get(self, request, *args, **kwargs):
ad_account = self.get_ad_account(kwargs.get('ad_account_id'))
campaigns = self.get_campaigns(ad_account.get('id')) \
if ad_account else None
context = {'campaigns': campaigns, 'ad_account': ad_account}
return render(request, 'app/campaigns/index.html', context)
Im my campaigns/index.html I have:
{% extends "app/empty_page.html" %}
{% load render_table from django_tables2 %}
{% block content %}
{% if ad_account %}
{% render_table context %}
{% endif %}
{% endblock %}
However this gives me the error: Expected table or queryset, not 'str'.
ANy help will be greately appreciated.
Right now I generate the table using this piece of code:
<table class="table table-bordered table-striped" id="campaigns">
<thead>
<tr>
<th> #</th>
<th> Campaign Name</th>
<th> Campaign Objective</th>
<th> Campaign Effective Status</th>
</tr>
</thead>
<tbody>
{% for campaign in campaigns %}
<tr>
<td> {{ forloop.counter }} </td>
<td>
<a href="/ad_accounts/{{ ad_account.id }}/campaigns/{{ campaign.id }}/ad_sets">
{{ campaign.name }} </a>
</td>
<td> {{ campaign.objective }}</td>
<td> {{ campaign.effective_status }} </td>
</tr>
{% endfor %}
</tbody>
</table>

You should pass a Table instance or queryset to the render_table tag.
{% render_table campaigns %}

Related

How to build a table of objects without knowing their attributes?

I'm trying to build a table dynamically in my django template. I got the column names in my views.py and also got the contents of the table:
table = tenant_tables.models[table_name].objects.all()
headers = table.model._meta.get_fields(include_parents=True, include_hidden=False)
context = {'table': table, 'headers': headers}
return render(request, template_name=template_name, context=context)
Based on the received data, I want to build a table using a template, but I don't know how to sort through all the attributes of the object
<table
id="example"
class="table table-striped data-table"
style="width: 100%"
>
<thead>
<tr>
{% for header in headers %}
<th>{{header.verbose_name}}</th>>
{% endfor %}
</tr>
</thead>
<tbody>
{% for obj in table %}
<tr>
<td>{{obj}}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
{% for header in headers %}
<th>{{header.verbose_name}}</th>>
{% endfor %}
</tr>
</tfoot>
</table>
Can I implement this or should I create a view for each model in my application?
Yes, it's possible to implement this. But first you need to implement a custom filter which works like the getattr function in python.
Then you can do this:
...
<tbody>
{% for obj in table %}
<tr>
{% for header in headers %}
<td>{{ obj | getattr_filter:header }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
...
The filter should looks something like this:
#register.filter(name='getattr_filter')
def getattr_filter(obj, attribute):
return getattr(obj, attribute, None)
Check the docs for more details on how to implement a custom template filter.

Django - update inline formset not updating

I'm trying to create an update view which has a few inline formset's in it but for some reason I'm seeing 'id: This field is required.' & none of the inline formset values being set when I click the update button. The fields themselves actually have values in them in the template so I'm not sure why the inline formsets would be empty when trying to save.
Models.py
class ProjectUpdateForm(forms.ModelForm):
class Meta:
model = Project
fields = ('name', 'details')
Views.py
class ProjectUpdateView(LoginRequiredMixin, UpdateView):
model = Project
template_name = 'home/project/project_update.html'
context_object_name = "project"
form_class = ProjectUpdateForm
def get_context_data(self, **kwargs):
ReviewChildFormset = inlineformset_factory(
Project, AdoptedBudgetReview, fields=('project', 'review'), can_delete=False, extra=0
)
itemNames = [{'item': item} for item in ['Concept & Feasibility', 'Planning & Design', 'Procurement', 'Delivery & Construction', 'Finalisation']]
EstimatedBudgetChildFormset = inlineformset_factory(
Project, EstimatedBudget, fields=('project', 'item', 'cost', 'time'), can_delete=False, formset=EstimatedInlineFormset, extra=0, widgets={'item': forms.Select(attrs={'disabled': True})},
)
FutureExpenditureFormset = inlineformset_factory(
Project, FutureExpenditure, fields=('project', 'byear', 'internalFunding', 'externalFundingSource', 'externalFunding'), can_delete=False, extra=0,
)
PreviousExpenditureFormset = inlineformset_factory(
Project, PreviousExpenditure, fields=('project', 'byear', 'internalFunding', 'externalFunding'), can_delete=False, extra=0,
)
initial = [{'priority': priority} for priority in Priority.objects.all()]
PriorityChildFormset = inlineformset_factory(
Project, ProjectPriority, fields=('project', 'priority', 'score'), can_delete=False, extra=0, widgets={'priority': forms.Select(attrs={'disabled': True})},
)
context = super().get_context_data(**kwargs)
if self.request.POST:
context['adoptedreviews'] = ReviewChildFormset(self.request.POST, instance=self.object)
context['estimatedbudget'] = EstimatedBudgetChildFormset(self.request.POST, initial=itemNames, instance=self.object)
context['futureexpenditure'] = FutureExpenditureFormset(self.request.POST, instance=self.object)
context['previousexpenditure'] = PreviousExpenditureFormset(self.request.POST, instance=self.object)
context['priorities'] = PriorityChildFormset(self.request.POST, initial=initial, instance=self.object)
else:
context['adoptedreviews'] = ReviewChildFormset(instance=self.object)
context['estimatedbudget'] = EstimatedBudgetChildFormset(initial=itemNames, instance=self.object)
context['futureexpenditure'] = FutureExpenditureFormset(instance=self.object)
context['previousexpenditure'] = PreviousExpenditureFormset(instance=self.object)
context['priorities'] = PriorityChildFormset(initial=initial, instance=self.object)
return context
def form_valid(self, form):
context = self.get_context_data()
adoptedreview = context["adoptedreviews"]
estimatedbudget = context["estimatedbudget"]
prioritycriteria = context["priorities"]
futureexpenditure = context["futureexpenditure"]
previousexpenditure = context["previousexpenditure"]
form.instance.creator = self.request.user
if adoptedreview.is_valid() and estimatedbudget.is_valid() and previousexpenditure.is_valid() and futureexpenditure.is_valid and prioritycriteria.is_valid():
self.object = form.save()
adoptedreview.instance = self.object
estimatedbudget.instance = self.object
futureexpenditure.instance = self.object
previousexpenditure.instance = self.object
prioritycriteria.instance = self.object
adoptedreview.save()
estimatedbudget.save()
previousexpenditure.save()
futureexpenditure.save()
prioritycriteria.save()
else:
return self.form_invalid(form)
return super(ProjectCreateview, self).form_valid(form)
Template
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Update Project</legend>
{{ form|crispy }}
</fieldset>
<h2>Adopted Budget Review</h2>
<!-- {{ adoptedreviews|crispy }} -->
<table class="table table-light">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">BR1</th>
<th scope="col">BR2</th>
<th scope="col">BR3</th>
<th scope="col">BR4</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Amount</th>
{{ adoptedreviews.management_form }}
{% for adrform in adoptedreviews.forms %}
{% for field in adrform.visible_fields %}
<td>
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
{% endfor %}
</tr>
</tbody>
</table>
<h2>Estimated Budget - Breakdown Yr1</h2>
<!-- {{ estimatedbudget|crispy }} -->
<table class="table table-light">
{{ estimatedbudget.management_form }}
<thead>
<tr>
<th scope="col">Item - Description</th>
<th scope="col">Anticipated % cost</th>
<th scope="col">Anticipated time - weeks</th>
</tr>
</thead>
{% for form in estimatedbudget.forms %}
<tr>
<td>
{{ form.errors }}
<h4>{{ form.item.value }}</h4>
{{ form.item.as_hidden }}
</td>
<td>
{{ form.cost }}
</td>
<td>
{{ form.time }}
</td>
</tr>
{% endfor %}
</table>
<h2>Future Project Expenditure</h2>
<!-- {{ futureexpenditure|crispy }} -->
<table class="table table-light">
{{ futureexpenditure.management_form }}
{% for form in futureexpenditure.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th scope="col">{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tbody>
<tr class="{% cycle row1 row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
</tbody>
{% endfor %}
</table>
<h2>Previous Project Expenditure</h2>
<table class="table table-light">
<!-- {{ previousexpenditure|crispy }} -->
{{ previousexpenditure.management_form }}
{% for form in previousexpenditure.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th scope="col">{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tbody>
<tr class="{% cycle row1 row2 %} previous_formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
</tbody>
{% endfor %}
</table>
<h2>Priority Criteria</h2>
<!-- {{ priorities|crispy }} -->
<table class="table table-light">
<tbody>
{{ priorities.management_form }}
{% for priority in priorities.forms %}
<tr>
<td>
{{ priority.priority.errors.as_ul }}
{% for value, name in priority.priority.field.choices %}
{% if value == priority.priority.value %}
<h4>{{ name }}</h4>
{% endif %}
{% endfor %}
{{ priority.priority.as_hidden }}
</td>
<td>
{{ priority.score.errors.as_ul }}
{{ priority.score }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Update Project</button>
</div>
</form>
Whenever one renders a forms manually one should remember to always render it's hidden fields, more so for a formset / inlineformset since it automatically adds some hidden fields to the form. Since the formset is updating multiple instances of course there needs to be something present in the formset to indicate which instance is which, which is done by hidden fields here.
Hence you need to render the hidden fields of your formsets forms:
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Update Project</legend>
{{ form|crispy }}
</fieldset>
<h2>Adopted Budget Review</h2>
<!-- {{ adoptedreviews|crispy }} -->
<table class="table table-light">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">BR1</th>
<th scope="col">BR2</th>
<th scope="col">BR3</th>
<th scope="col">BR4</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Amount</th>
{{ adoptedreviews.management_form }}
{% for adrform in adoptedreviews.forms %}
{% for hidden in adrform.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in adrform.visible_fields %}
<td>
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
{% endfor %}
</tr>
</tbody>
</table>
<h2>Estimated Budget - Breakdown Yr1</h2>
<!-- {{ estimatedbudget|crispy }} -->
<table class="table table-light">
{{ estimatedbudget.management_form }}
<thead>
<tr>
<th scope="col">Item - Description</th>
<th scope="col">Anticipated % cost</th>
<th scope="col">Anticipated time - weeks</th>
</tr>
</thead>
{% for form in estimatedbudget.forms %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<tr>
<td>
{{ form.errors }}
<h4>{{ form.item.value }}</h4>
{{ form.item.as_hidden }}
</td>
<td>
{{ form.cost }}
</td>
<td>
{{ form.time }}
</td>
</tr>
{% endfor %}
</table>
<h2>Future Project Expenditure</h2>
<!-- {{ futureexpenditure|crispy }} -->
<table class="table table-light">
{{ futureexpenditure.management_form }}
{% for form in futureexpenditure.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th scope="col">{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tbody>
<tr class="{% cycle row1 row2 %} formset_row">
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
</tbody>
{% endfor %}
</table>
<h2>Previous Project Expenditure</h2>
<table class="table table-light">
<!-- {{ previousexpenditure|crispy }} -->
{{ previousexpenditure.management_form }}
{% for form in previousexpenditure.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th scope="col">{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tbody>
<tr class="{% cycle row1 row2 %} previous_formset_row">
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
</tbody>
{% endfor %}
</table>
<h2>Priority Criteria</h2>
<!-- {{ priorities|crispy }} -->
<table class="table table-light">
<tbody>
{{ priorities.management_form }}
{% for priority in priorities.forms %}
{% for hidden in priority.hidden_fields %}
{{ hidden }}
{% endfor %}
<tr>
<td>
{{ priority.priority.errors.as_ul }}
{% for value, name in priority.priority.field.choices %}
{% if value == priority.priority.value %}
<h4>{{ name }}</h4>
{% endif %}
{% endfor %}
{{ priority.priority.as_hidden }}
</td>
<td>
{{ priority.score.errors.as_ul }}
{{ priority.score }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Update Project</button>
</div>
</form>
Also since you have multiple formsets you should provide a prefix to them to provide name clashing (See Using more than one formset in a view):
if self.request.POST:
context['adoptedreviews'] = ReviewChildFormset(self.request.POST, instance=self.object, prefix='adoptedreviews_form')
context['estimatedbudget'] = EstimatedBudgetChildFormset(self.request.POST, initial=itemNames, instance=self.object, prefix='estimatedbudget_form')
context['futureexpenditure'] = FutureExpenditureFormset(self.request.POST, instance=self.object, prefix='futureexpenditure_form')
context['previousexpenditure'] = PreviousExpenditureFormset(self.request.POST, instance=self.object, prefix='previousexpenditure_form')
context['priorities'] = PriorityChildFormset(self.request.POST, initial=initial, instance=self.object, prefix='priorities_form')
else:
context['adoptedreviews'] = ReviewChildFormset(instance=self.object, prefix='adoptedreviews_form')
context['estimatedbudget'] = EstimatedBudgetChildFormset(initial=itemNames, instance=self.object, prefix='estimatedbudget_form')
context['futureexpenditure'] = FutureExpenditureFormset(instance=self.object, prefix='futureexpenditure_form')
context['previousexpenditure'] = PreviousExpenditureFormset(instance=self.object, prefix='previousexpenditure_form')
context['priorities'] = PriorityChildFormset(initial=initial, instance=self.object, prefix='priorities_form')
Note: You seem to have weird HTML (multiple tbody elements in a table??), and also you might want to reconsider having so many
formsets in a page, this can be considered bad for UX purposes (This
can be really confusing for the user, not to mention the developer
too). One page should ideally serve one purpose to the user.

I was going to render the saved data into html table but found this error

<tbody>
{% for publication in publication_list %}
<tr>
<td>{{%publication.addpublication%}}</td>
</tr>
{% endfor %}
</tbody>
views.py
def publicationlist(request):
context = {'publication_list' : AddPublication.objects.all()}
return render(request,"publication_list.html", context)
TemplateSyntaxError at /addpublication/publicationlist/
Could not parse the remainder: '%publication.addpublication%' from '%publication.addpublication%'
# You have to remove % in your td tag of html
<tbody>
{% for publication in publication_list %}
<tr>
<td>{{publication.addpublication}}</td>
</tr>
{% endfor %}
</tbody>
For tags like for, if...:
{% for %}{% endfor %}
For context variables:
{{ my_context_variable }}

Toggle Checkbox in Django and Write to Database

I have some model
from django.db import models
class Model1(models.Model):
title = models.CharField(max_length=300)
boolean1 = models.BooleanField(default=False)
boolean2 = models.BooleanField(default=False)
and am currently displaying all database entries in a template via the following bootstrap table:
<div class = 'table-responsive'>
<table class='table table-striped'>
<thead>
<th>Title</th>
<th>Boolean 1</th>
<th>Boolean 2</th>
</thead>
{% if model1_list %}
{% for Model1 in model1_list %}
<tbody>
<tr>
<td>{{ Model1.title }}</td>
<td>{{ Model1.boolean1 }}</td>
<td>{{ Model1.boolean2 }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
I'd like to display the boolean values as checkboxes rather than text, and to be able to check and uncheck the values and have it be reflected in the database (i.e., if the database is checked, the value should be True).
What would be a way to implement this?
Just use IF's:
<div class = 'table-responsive'>
<table class='table table-striped'>
<thead>
<th>Title</th>
<th>Boolean 1</th>
<th>Boolean 2</th>
</thead>
{% if model1_list %}
{% for Model1 in model1_list %}
<tbody>
<tr>
<td>{{ Model1.title }}</td>
<td>
<div class="checkbox">
<label><input type="checkbox" {% if Model1.boolean1 %} checked {% endif %}>Boolean 1</label>
</div>
</td>
<td>
<div class="checkbox">
<label><input type="checkbox" {% if Model1.boolean2 %} checked {% endif %}>Boolean 2</label>
</div>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
When the user clicks, you want to send this information to the DB without refreshing the page? If yes, you need to do an ajax request to set this information to DB using JSON.Something like that:
$.ajaxFunction = function(){
var boolean1 = $("#boolean1").val(),
boolean2 = $("#boolean2").val(),
csrf_token = $("#csrf_token").val();
data_send = {
"boolean1": boolean1,
"boolean2": boolean2,
"csrfmiddlewaretoken": csrf_token
};
//jquery
$.ajax({
type: "post",
url: $("/url/ajax/").val(),
data: data_send,
success: function(data_receive){
if(data['boolean1']==true){
...
}
...
}
});
}
If no, you can just do a to POST this information and refresh the page!

django table information displayed twice

django table information displayed twice
Why is the Due date and time remaining appear twice? I am trying figure out what is that coming from. I am still learning django, slowly. Sometimes, I'm just having trouble.
Picture:
http://gyazo.com/cae11df54df3f558865a772529f97139.png
.html code
{% if toolsBorrowed %}
<table id="dataTable" width="100%" cellspacing="0" cellpadding="5" class="table table-hover">
<thead>
<tr>
<th>Tool Name</th>
<th>Owner</th>
<th>Due Date</th>
<th>Time Remaining</th>
</tr>
</thead>
<tbody id="myTable">
{% for tool in toolsBorrowed %}
{% query Request borrowerId=user.id as req %}
{% query userAcc pk=tool.owner as owner %}
<tr style="cursor: pointer;" onclick="document.location = '/view_tool/{{ tool.id }}/';">
<td>{{ tool.name }}</td>
<td>{% for o in owner %}{{ o.username }}{% endfor %}</td>
{% for r in req %}
<td>{{ r.dueDate }}</td>
<td>{{ r.dueDate | timeuntil }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<strong>You are not borrowing any tools.</strong>
{% endif %}
views.py
def borrowed(request):
context = {'toolsBorrowed': Tool.objects.filter(borrower = request.user.id),
'toolsLoan':Tool.objects.filter(owner = request.user.id).exclude(borrower = None),
'userAcc' : userAcc.objects,
'Request' : Request.objects,
}
return render(request, 'borrowed.html', context)
Any help would be great.