Editing the model in a ListView - django-models

I'm currently making a website for my parent's bakery. And I want to make a custom admin page for them so they can update their products with ease.
All I have so far is a ListView that displays all the products.
This is my model:
class menulist(models.Model):
name = models.CharField(max_length=120)
description = models.CharField(max_length=500)
price = models.DecimalField(decimal_places=1, max_digits=10, default=100.00)
category_choices = (
('breads', 'Breads'),
('cakes', 'Cakes'),
('hotfood', 'Hot Food'),
('porkrolls', 'Pork Rolls'),
('drinks', 'Drinks'),
('MISC', 'Misc'),
)
category = models.CharField(max_length=50, choices=category_choices, default='MISC',)
dateadded = models.DateField(auto_now_add=True)
dateupdated = models.DateField(auto_now=True)
img = models.ImageField(upload_to='products/', default='products/blank.jpg')
def __str__(self):
return self.name
The View:
class ProductAdminView(ListView):
template_name = 'menulistapp/product_admin.html'
queryset = menulist.objects.all()
The template:
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="row">
<table class="table table-striped table-hover ">
<thead class="thead-dark">
<tr>
<th style="width: 15%"scope="col"></th>
<th style="width: 55%" scope="col">Product Name</th>
<th scope="col">Category</th>
<th scope="col">Price</th>
<th scope="col">Date Added</th>
<th scope="col">Last Updated</th>
</tr>
</thead>
<tbody>
{% for obj in object_list %}
<tr>
<td class="align-middle"><img src="{{ obj.img.url }}" class="img-fluid"></td>
<td class="align-middle">{{ obj.name }}</td>
<td class="align-middle">{{ obj.get_category_display }}</td>
<td class="align-middle">${{ obj.price }}</td>
<td class="align-middle">{{ obj.dateadded }}</td>
<td class="align-middle">{{ obj.dateupdated }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
How do I separate the items into their own category tables?
And how do I make it so that each cell is editable with their own CharField, and there's a "SAVE" button at the bottom of each table?
EG:

You have to use the concept of forms to attain that
For more information, go through https://docs.djangoproject.com/en/2.1/topics/forms/

Related

How to add "caption" tag in TableBlock template in StreamField?

I'd like to add <caption> tag for tables created with TableBlock in StreamField, to make the tables more accessible and semantically correct. Right now, the default template doesn't have that tag. I'm not sure how I should be customizing the table.html template (from the default, and I'm not sure how to render the table if I make a custom class for the table block to add captioning.
<caption> must be <table>'s first child, that's why I need to tinker with the template. Anyone has doe this before?
<table>
<caption>Example Caption</caption> <--- Need this here
<thead>
<th>Header col 1</th>
<th>Header col 2</th>
</thead>
<tbody>
<tr>
<td>Cell col 1</td>
<td>Cell col 2</td>
</tr>
</tbody>
</table>
Take a look at the following code.
TableBlock.py
class TableHead(blocks.StructBlock):
table_head_text = blocks.ListBlock(blocks.CharBlock(max_length=120))
class TableRow(blocks.StructBlock):
table_row_text = blocks.ListBlock(blocks.CharBlock(max_length=120))
class TableBlock(blocks.StructBlock):
caption_text = blocks.CharBlock(max_length=120)
table_head = TableHead()
table_rows = blocks.ListBlock(TableRow())
class Meta:
template = 'wagtail_blocks/table.html'
You will notice that I have set the 'template' property in the 'Meta' class, so you will have to create that file too.
table.html
{% load wagtailcore_tags %}
<table>
<caption>{{ value.caption_text }}</caption>
<thead>
{% for header_text in value.table_head.table_head_text %}
<th>{{ header_text }}</th>
{% endfor %}
</thead>
<tbody>
{% for table_row in value.table_rows %}
<tr>
{% for table_row_text in table_row.table_row_text %}
<td>{{ table_row_text }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
Finally you can easily use your new TableBlock in any page like this
body = StreamField([
('table', TableBlock()),
])

AngularJS merge directives

I hate it when I repeat code. So I want to know if there is a better way of doing this.
I have 2 directives, they are very simple and very similar.
The 2 directives look like this:
.directive('pkFilterProducts', function () {
return {
restrict: 'A',
templateUrl: 'assets/templates/directives/pkFilterProducts.html',
scope: {
products: '=pkFilterProducts',
filters: '='
}
}
})
.directive('pkStateProducts', function () {
return {
restrict: 'A',
templateUrl: 'assets/templates/directives/pkStateProducts.html',
scope: {
products: '=pkStateProducts',
states: '='
}
}
})
The only difference is one accepts filters and the other accepts states.
The templates are very similar too:
<div class="col-md-6">
<h3>Excluded ({{ excluded.length }})</h3>
<div class="table-responsive" ng-show="excluded.length">
<table class="table table-hover">
<thead>
<tr>
<th class="image-column"></th>
<th>Title</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in products | exclude: filters as excluded">
<td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
<td>{{ product.shortTitle }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-md-6">
<h3>Included ({{ included.length }})</h3>
<div class="table-responsive" ng-show="included.length">
<table class="table table-hover">
<thead>
<tr>
<th class="image-column"></th>
<th>Title</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in products | include: filters as included">
<td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
<td>{{ product.shortTitle }}</td>
</tr>
</tbody>
</table>
</div>
</div>
and
<div class="col-md-6">
<h3>Excluded ({{ excluded.length }})</h3>
<div class="table-responsive" ng-show="excluded.length">
<table class="table table-hover">
<thead>
<tr>
<th class="image-column"></th>
<th>Title</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in products | statesExclude: states as excluded">
<td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
<td>{{ product.shortTitle }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-md-6">
<h3>Included ({{ included.length }})</h3>
<div class="table-responsive" ng-show="included.length">
<table class="table table-hover">
<thead>
<tr>
<th class="image-column"></th>
<th>Title</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in products | statesInclude: states as included">
<td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
<td>{{ product.shortTitle }}</td>
</tr>
</tbody>
</table>
</div>
</div>
again, the only different is the ng-repeat filter. Instead of using include or exclude it uses statesInclude and statesExclude.
Is there a way I can combine these too? Maybe use a variable for the filter?
It might sound a bit too hacky but I'd join the two ng-repeats on a single template and use ng-ifs to make them check for which is valid/should run. Example:
<tr ng-if="states"
ng-repeat="product in products | statesInclude: states as included">
<td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
<td>{{ product.shortTitle }}</td>
</tr>
<tr ng-if="filters"
ng-repeat="product in products | include: filters as included">
<td><img class="img-responsive" ng-src="{{ product.image }}" /></td>
<td>{{ product.shortTitle }}</td>
</tr>
You could then perhaps use a single directive declaration:
.directive('pkProducts', function () {
return {
restrict: 'A',
templateUrl: 'assets/templates/directives/pkProducts.html',
scope: {
products: '=pkFilterProducts',
filters: '=',
states: '='
}
}
})
I agree with wdanda.
Another solution would be to pass an boolean to your filter. Depending on the boolean you need to make it behave different.
See this for reference.

How can I can make ng-repeat as group?

Here Is my code.
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<div class="table-responsive">
<div id="exportable">
<table class="table table-striped table-bordered table-hover dataTable" id="example">
<thead>
<tr>
<th style="background-color: #f5f5f5;">Device Number</th>
<th style="background-color: #f5f5f5;">Name</th>
<th style="background-color: #f5f5f5;">MobileNumber</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="obj in SubscriptionList">
<td>
<button ng-if="obj.expanded" ng-click="obj.expanded = false">-</button>
<button ng-if="!obj.expanded" ng-click="obj.expanded = true">+</button>
</td>
<td>{{ obj.DEVICENUMBER}}</td>
<td>{{ obj.NAME}}</td>
<td>{{ obj.MOBILENUMBER}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- /.table-responsive -->
</div>
</div>
<!-- /.row -->
Result Is Coming like
Name Mobile Device
A 112 Nokia
A 112 Samsung
B 111 Videocon
B 111 LG
I want There is an expand button on Name,when I expand below all the details will show
You could use ng-repeat-start and ng-repeat-end and add an additional tr to your table with an ng-if. That way when you click on the button there will be an extra row just under the one which holds the button.
<div class="row">
<div class="col-lg-12">
<div class="table-responsive">
<div id="exportable">
<table class="table table-striped table-bordered table-hover dataTable" id="example">
<thead>
<tr>
<th style="background-color: #f5f5f5;">Device Number</th>
<th style="background-color: #f5f5f5;">Name</th>
<th style="background-color: #f5f5f5;">MobileNumber</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="obj in SubscriptionList">
<td>
<button ng-if="obj.expanded" ng-click="obj.expanded = false">-</button>
<button ng-if="!obj.expanded" ng-click="obj.expanded = true">+</button>
</td>
<td>{{ obj.DEVICENUMBER }}</td>
<td>{{ obj.NAME }}</td>
<td>{{ obj.MOBILENUMBER }}</td>
</tr>
<tr ng-repeat-end ng-if="obj.expanded">
<td colspan="4">expanded</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>

Angular OrderBy with dynamic headers

How can I sort a table given dynamic headers with angular? All of the examples I can find use static headers. My first issue is that ng-click isn't updating orderByField.
My best shot below: HTML:
<table class="table table-condesnsed table-bordered">
<thead>
<tr>
<th ng-repeat="header in report_headers"
ng-click="orderByField[header]; reverseSort = !reverseSort">
{{ header }}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="quote in paginated_quotes">
<td ng-repeat="elem in quote |orderBy:orderByField:reverseSort">
<span ng-if="!isNumber(elem.value)">
{{ elem.value | limitTo:8 }}... {{ elem.unit }}</span>
<span ng-if="isNumber(elem.value)">
{{ elem.value | number:0 }} {{ elem.unit }}</span>
</td>
</tr>
</tbody>
</table>
JS:
$scope.orderByField = 'UUID';
$scope.reverseSort = false;
Thanks
I think you want
<th ng-repeat="header in report_headers"
ng-click="orderByField = header; reverseSort = !reverseSort">
other than that it looks like it should work

AngularJS ng-include finished

I'm loading a large amount of data using ng-include.
I'd like to know if there is a way to know when a template is "rendered", because sometimes it seems like it's been "frozen", because I want to do a "loading screen" or something.
Thx.
Here's the code
controller code:
$scope.layout = {
current: 'single-table.html'
};
$scope.layout.get = function() {
return $scope.layout.current;
};
templates:
main.html
<div class="btn-group">
<button ng-click="layout.current = 'single-table.html'">Single</button>
<button ng-click="layout.current = 'multiple-table.html'">Multiple</button>
</div>
<div ng-include="layout.get()"></div>
single-table.html
<table class="table table-bordered">
<thead>
<th ng-repeat="column in columns">{{ column.title }}</th>
</thead>
<tbody>
<tr ng-repeat="record in records">
<td ng-repeat="field in record.fields"
ng-controller="FieldController"
ng-class="getClass()">
{{ field.display }}
</td>
</tr>
</tbody>
</table>
multiple-table.html
<table class="table table-bordered" ng-repeat="record in records">
<tbody>
<tr ng-repeat="field in record.fields">
<th>{{ columns[$index].title }}</th>
<td ng-controller="FieldController" ng-class="getClass()">
{{ field.display }}
</td>
</tr>
</tbody>
</table>
EDIT
I'm using version 1.2.0
One solution (probably not the best) is doing this (no ng-include)
<table class="table table-bordered" ng-show="layout.current == 'single-table.html'">
<thead>
<th ng-repeat="column in columns">{{ column.title }}</th>
</thead>
<tbody>
<tr ng-repeat="record in records">
<td ng-repeat="field in record.fields"
ng-controller="FieldController"
ng-class="getClass()">
<span lud-run="{{ field.ng_directive }}"></span>
</td>
</tr>
</tbody>
</table>
<table class="table table-bordered" ng-repeat="record in records" ng-show="layout.current == 'multiple-table.html'">
<tbody>
<tr ng-repeat="field in record.fields">
<th>{{ columns[$index].title }}</th>
<td ng-controller="FieldController" ng-class="getClass()">
<span lud-run="{{ field.ng_directive }}"></span>
</td>
</tr>
</tbody>
</table>
I have only 20 records, but (is not in the code), each cells loads a custom directive depends on the data type (string, date, datetime, image...). This "solution" I think runs the same data twice (ng-show, not ng-if), but when a switch the layout mode there is no "lag".
You can use the onload hook on ng-include to update a variable when the include has finished rendering. If you set it to true on clicking your button, then revert it back to false in onload, you should be able to leverage it to temporarily display a loading screen.

Resources