I have three models.
class Supplier(models.Model):
name = models.CharField(max_length=200, null=True)
class Order(models.Model):
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
class Product(models.Model):
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, null=True, blank=True)
on_order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True, blank=True)
I can display a table of all the products of a given order. However, I cannot seem to render the name of that supplier on the html page like <h4> Supplier: {{order.supplier}}</h4>
this is the view:
def PurchaseOrder(request, pk_order):
orders = Order.objects.get(id=pk_order)
products = Product.objects.filter(
on_order_id=pk_order).prefetch_related('on_order')
total_products = products.count()
supplier = Product.objects.filter(on_order_id=pk_order).prefetch_related('on_order')
context = {
'supplier': supplier,
'products': products,
'orders': orders,
'total_products': total_products, }
return render(request, 'crmapp/purchase_order.html', context)
here is my template:
{% extends 'crmapp/base.html' %}
{% load static %}
{% block content %}
<div class='main-site>'>
<h4> Supplier: {order.supplier}}</h4> **<----Does not work**
<h5>Order Number: {{order.id}}</h5> **<----Does not work**
<h5>Created on: {{order.date_created | date:"d/m/Y"}}</h5> **<----Does not work**
<h6>Total Items on Order: {{total_products}}</h6>
<input type="search" placeholder="Search any field..." class="form-control search-input" data-table="customers-list"/>
<table class="table table js-sort-table mt32 customers-list" id='myTable'>
<thead class="table" >
<tr>
<th class='header' onclick="sortTable(0)" scope="col">ID</th>
<th class='header' onclick="sortTable(1)" scope="col">Description</th>
<th class='header' onclick="sortTable(2)" scope="col">Cost</th>
<th class='header' onclick="sortTable(3)" scope="col">Order Quantity</th>
</tr>
</thead>
<tbody>
<tr>
{% for product in products %}
<td> {{product.id}}</td>
<td><h6><strong>{{product.description}}</strong></h6></td>
<td>£{{product.costprice |floatformat:2}}</td>
<td>{{product.on_order_quantity |floatformat:0}}</td>
</tr>
</tbody>
{% endfor %}
{% endblock %}
I've tried so hard... and didn't get very far.
Please help...
in context you write "orders", but in template you ask for "order", which is not defined. Try
<h4> Supplier: {{orders.supplier}}</h4>
Related
I am trying to show number of articles in each category in my django project. But it shows category id instead of category_name. I want to display category_name and the corresponding number of articles.
blog/views.py
def searchView(request):
statistics = Post.objects.values('cid').annotate(num_articles = Count('cid')).order_by()
return render(request, 'blog/search.html', {'statistics': statistics})
blog/search.html -> here stat.cid shows the category id but I want to show category_name here.
{% extends 'users/base.html' %}
{% block content %}
<div class="container">
<br>
<div class="row text-center">
<div class="col-md-3"> </div>
<div class="col-md-6">
<h4 class="p-2 mb-2 bg-secondary text-white">POPULAR CATEGORIES!!</h4>
<table id="myTable" class="table table-bordered table-hover table-striped shadow-sm bg-white rounded">
<thead>
<tr>
<th>Category</th>
<th>Articles Available</th>
</tr>
</thead>
<tbody>
{% for stat in statistics %}
<tr>
<td>
{{ stat.cid }}
</td>
<td>
{{ stat.num_articles }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}
blog/models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth import get_user_model
from django.urls import reverse
from ckeditor.fields import RichTextField
# Create your models here.
class Category(models.Model):
cid = models.AutoField(primary_key=True)
category_name = models.CharField(max_length=100)
def __str__(self):
return self.category_name
class Post(models.Model):
aid = models.AutoField(primary_key=True)
image = models.ImageField(default='blog-default.png', upload_to='images/')
title = models.CharField(max_length=200)
content = RichTextField()
created = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
cid = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='specialization')
approved = models.BooleanField('Approved', default=False)
like = models.ManyToManyField(get_user_model(), related_name='likes', blank=True)
def __str__(self):
return self.title
Post.objects.values('cid') would only give you the pk of the Category. To access the category_name of the Category you should also include that in the values():
# Note the double underscore between cid and category_name
`Post.objects.values('cid', 'cid__category_name')`
Now that the category_name is available, access it in the template like this:
{{ stat.cid__category_name }}
While this is specific to your case, a better answer is here:
https://stackoverflow.com/a/27181936/10951070
I would be going at this from the opposite direction, meaning I would be accessing this data from Category rather than from Post which for some reason you call statistics.
First off I'd suggest you to use a ListView and then I'd proceed as follows:
# views
from django.views.generic import ListView
class CategoryListView(ListView):
model = Category
template_name = 'blog/search.html'
context_object_name = "categories"
# template
<table>
<thead>
...
</thead>
<tbody>
{% for category in categories %}
<tr>
<td>{{ category.cid }}</td>
<td>{{ category.post_set.count }}</td>
</tr>
{% endfor %}
</tbody>
</table>
If you add a related_name in your Post model in the cid attribute and call it posts, you can then in the template write category.posts.count which is more readable. This is just a personal preference and definitely not a rule.
I have 2 models; Invoice and Expense. Both have a date field. I want to create a django-filter where I put a start-date and end-date and get the result on 2 differents table in the same HTML page. So far I need to use 2 different filters and if I put the date in the Invoice Filter it clears the Expense Filter. Same if I put the date in the Expense Filter it clears the Income Filter.
Here is my filters.py
class DashboardIncomeFilter(django_filters.FilterSet):
start_date = DateFilter(field_name = "invoice_date", lookup_expr='gte', label='Start Date')
end_date = DateFilter(field_name = "invoice_date", lookup_expr = 'lte', label = 'End Date')
class Meta:
model = Invoice
fields = '__all__'
exclude = ['invoice_slug', 'therapist', 'invoice_date', 'service', 'customer', 'invoice_no', 'price', 'quantity', 'total', 'payment', 'balance']
class DashboardExpenseFilter(django_filters.FilterSet):
exp_start_date = DateFilter(field_name = "expense_date", lookup_expr='gte', label='Start Date')
exp_end_date = DateFilter(field_name = "expense_date", lookup_expr = 'lte', label = 'End Date')
class Meta:
model = Expense
fields = '__all__'
exclude = ['expense_date', 'vendor', 'expense_category', 'description','amount']
Than on my dashboard.html
{% block content %}
<center><h3>DASHBOARD</h3><br/>
<h3>Todays Date: {{ month }} {{ current_day }}, {{ year }} # {{ current_time }}</h3><br/>
<div class="row">
<div class="col">
<div class="card card-body"><h4>Incomes Filter</h4><br/>
<form method="get">
{{ ResultFilter.form }}
<button class="btn btn-primary" type="submit">
Search...</button>
<a class="btn btn-primary" href="{% url 'Dashboard' %}" role = "button">Reset</a>
</form>
</div><br/>
<table style="width: 80%" class="table table-primary table-bordered table-striped">
<thead>
<tr>
<th scope="col">Total Incomes</th>
<th scope="col">Total Threatments</th>
<th scope="col">Days Open</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="row">{{ income_total }} IDR</td>
<td scope="col">{{ threatments }}</td>
<td scope="col">{{ days_open }}</td>
</tr>
</tbody>
</table>
</div><br/>
<div class="col">
<div class="card card-body"><h4>Expenses Filter</h4><br/>
<form method="get">
{{ OutcomeFilter.form }}
<button class="btn btn-primary" type="submit">
Search...</button>
<a class="btn btn-primary" href="{% url 'Dashboard' %}" role = "button">Reset</a>
</form>
</div><br/>
<table style="width: 80%" class="table table-primary table-bordered table-striped">
<thead>
<tr>
<th scope="col">Total Expenses</th>
<th scope="col">Personnal Expenses</th>
<th scope="col">Profit +/-</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="col">{{ expense_total }} IDR</td>
<td scope="col">{{ personnal_expense }} IDR</td>
<td scope="col">{{ profit }} IDR</td>
</tr>
</tbody>
</table>
</div>
</div>
</div><br/>
Finally, my views.py
ResultFilter = DashboardIncomeFilter(request.GET, queryset=invoice_list)
invoice_list = ResultFilter.qs
OutcomeFilter = DashboardExpenseFilter(request.GET, queryset=expense_list)
expense_list = OutcomeFilter.qs
All the fields are excluded since I only want to filter on the invoice_date and expense_date field at the same time. Thanks.
When you submit whichever of the filters you specified, it does a GET request with the otther two filter values belonging to the other table not specified.
I've never tried this, but I expect that you can force it to submit all four with either filter submit by defining some null filters. same name as the other table, a method argument, pointing at a method that does nothing at all. Something like
class DashboardIncomeFilter(django_filters.FilterSet):
start_date = DateFilter(field_name = "invoice_date", lookup_expr='gte', l abel='Start Date')
end_date = DateFilter(field_name = "invoice_date", lookup_expr = 'lte', label = 'End Date')
# no-op filters
exp_start_date = DateFilter(field_name = "expense_date",
method = no_op, widget=forms.HiddenInput, label='Start Date') # label not needed?
exp_end_date = DateFilter(field_name = "expense_date",
method = no_op, widget=forms.HiddenInput, label = 'End Date')
class Meta:
model = Invoice
fields = '__all__'
exclude = ['invoice_slug', 'therapist', 'invoice_date', 'service', 'customer', 'invoice_no', 'price', 'quantity', 'total', 'payment', 'balance']
def no_op( self, qs, name, value):
return qs
Similarly but "mirror imaged" for the other table.
widget=forms.HiddenInput ought to make these fields invisible to the users. See Django forms docymentation and this answer.
Let us know if it works.
In this case, since the filter fields are identical, it might also work if you give the filters for both tables identical names, so the same filter is applied to both tables. Of course, that's assuming you do want to apply the same dates to both tables.
I have the following models
AcsObject class
class AcsObjects(models.Model):
object_id = models.IntegerField(primary_key=True)
object_type = models.ForeignKey('AcsObjectTypes', db_column='object_type')
context = models.ForeignKey('self', blank=True, null=True)
security_inherit_p = models.BooleanField()
creation_user = models.IntegerField(blank=True, null=True)
Projects class
class ImProjects(models.Model):
project = models.ForeignKey('AcsObjects',related_name='project', on_delete=False, primary_key=True)
project_name = models.CharField(max_length=1000)
project_nr = models.CharField(max_length=100)
project_path = models.CharField(max_length=100)
TimesheetTasks class
class TimesheetTasks(models.Model):
task = models.ForeignKey('Projects', related_name='t_task', on_delete=False, primary_key=True)
uom = models.ForeignKey('Categories', related_name='u_uom', on_delete=False)
planned_units = models.FloatField(blank=True, null=True)
billable_units = models.FloatField(blank=True, null=True)
I wrote the following code into views.py file.
class TimesheetData(TemplateView):
template_name = 'timesheet.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["da"] = TimesheetTasks.objects.all()
return context
I want to print a project_name but it is giving me a task_id ( task_id and project_id are same) using jinja template.
timesheet.html
<body>
<p> {{da}} </p>
<table class="table table-light">
<thead class="thead-light">
<tr>
<th>Task </th>
</tr>
</thead>
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task}} </td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
It is giving me a blank output
Output
That's simply just because you're not access to product_name field yet.
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task}} </td>
</tr>
{% endfor %}
</tbody>
With this, Jinja just render the task id (project id), because Jinja think that you're not need any other information but just the foreign key value. So to be able to see the project_name, you should use this instead: timesheet.task.project_name, it does the job.
<tbody>
{% for timesheet in da %}
<tr>
<td> {{timesheet.task.project_name}} </td>
</tr>
{% endfor %}
</tbody>
Just want to mention that this could lead to another issue (performance issue) when Jinja have to query the data when render the template. To get rid of that, consider to use select_related which is an API of Django Queryset, check it out and gain some experiment that API, it really useful when using Django.
I ve an error when loading 'group_list.html' :
Reverse for 'group-edit' not found. 'group-edit' is not a valid view function or pattern name.
If I supress this href reference, it works but I need this to be able to edit a group instance
this is my views.py for group_edit:
def group_edit(request, group_id):
group_form = GroupFormEdit(instance=Group.objects.get(id=group_id))
if request.method == "POST":
group_form = GroupForm(request.POST, instance=Group.objects.get(id=group_id))
if group_form.is_valid():
group_form.save()
messages.success(request, 'Group saved') # message for inform user of success - See messages in html file
return redirect('home')
else:
group_form = GroupForm()
return render(request, 'imports/group_edit.html', {
"group_form": group_form,
})
my group_list.html:
{% block page %}
<div class="panel-body">
<table class="table table-bordered table-hover table-striped col-md-3">
<thead class="thead-dark">
<tr class="text-center">
<th>Group Name</th>
<th>Parent Name</th>
</tr>
</thead>
<tbody>
{% for group in groups %}
<tr>
<td scope="row" class="col-md-3">{{ group.group_name }}</td>
<td class="col-md-3">{{ group.groupParent_id }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
my urls.py:
urlpatterns = [
path('', views.imports_last, name='home'),
path('company_create/', views.company_create, name='company_creation'),
path('group_create/', views.group_create, name='group_creation'),
path('group_edit/', views.group_edit, name='group_edit'),
path('group_list/', views.group_list, name='group_list'),
]
and models.py:
class Group(models.Model):
group_id = models.AutoField(primary_key=True)
groupParent_id = models.ForeignKey('self', blank=True, null=True, related_name='Parent', on_delete=models.CASCADE)
group_name = models.CharField(max_length=100, null=False, blank=False, unique=True)
def __str__(self):
return '{}'.format(self.group_name)
I find my pain point;
it is in the url
I should mention that I want to add a variable :
path('group_edit/<int:group_id>/', views.group_edit, name='group-edit'),
I'm trying to display some tables, but they come up empty. The part that gets me is the number of rows is correct, but they are completely blank. If the table has 9 entries, I get 9 empty rows.
The same code is working for a different table
tables.py:
class VouchersTable(tables.Table):
class meta:
model = Vouchers
fields = ('event_name', 'pk', 'valid_start', 'valid_end', 'lab_duration', 'user_email', 'redeem_date' )
views.py:
class ReportsView(LoginRequiredMixin, TemplateView):
template_name = 'reports.html'
def get_context_data(self, **kwargs):
context = super(ReportsView, self).get_context_data(**kwargs)
vouchers = VouchersTable(Vouchers.objects.all())
RequestConfig(self.request, paginate=False).configure(vouchers)
context['vouchers'] = vouchers
return context
reports.html:
{% extends "base.html" %}
{% load render_table from django_tables2 %}
{% block content %}
{% render_table vouchers %}
{% endblock content %}
models.py:
class Vouchers(models.Model):
creator_uid = models.IntegerField()
user_id = models.IntegerField()
username = models.CharField(max_length=255)
user_email = models.CharField(max_length=100)
event_name = models.CharField(max_length=255)
event_code = models.IntegerField()
valid_start = models.IntegerField()
valid_end = models.IntegerField()
redeemed = models.IntegerField()
redeem_date = models.IntegerField()
lab_version = models.CharField(max_length=40)
lab_model = models.IntegerField()
lab_id = models.IntegerField()
lab_duration = models.IntegerField()
resulting html (empty lines removed):
<div class="table-container">
<table>
<thead>
<tr>
</tr>
</thead>
<tbody>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
<tr class="odd">
</tr>
<tr class="even">
</tr>
</tbody>
</table>
</div>
Oh well...
You've declared the table like this:
class VouchersTable(tables.Table):
class meta:
model = Vouchers
fields = ('event_name', 'pk', 'valid_start', 'valid_end', 'lab_duration', 'user_email', 'redeem_date' )
The correct way to write it is class Meta (Meta with a capital M): https://github.com/jieter/django-tables2