I am making a HTML table to display boxes (in a stockroom) that have been added, removed and changed. The headings are denoting the owner of the box, the type of change that has occurred and the new content of the box.
Im using Django for my backend.
Can I translate the values in the 'Type of Change' into English words rather than the symbols (~, - and +)? I am using Django simple-history to record changes to my models and it returns these symbols. I would like my table to read 'Changed', 'Removed' and 'Added' in place of '~', '-' and '+' respectfully.
This is the view.py:
def dashboard(request):
box_content_history = Box.history.all().order_by('-history_date')
return render(request, 'main_app/dashboard.html', {""box_content_history":box_content_history})
The HTML:
<table id="asset_changes_datatable">
<thead>
<tr>
<th>Owner</th>
<th>Type of Change</th>
<th>Box Contents</th>
</tr>
</thead>
<tbody>
{% for item in box_content_history %}
<tr>
<td>{{ item.project_assigned_to }}</td>
<td>{{ item.history_type }}</td>
<td>{{ item.box_contents }}</td>
</tr>
{% endfor %}
</tbody>
</table>
As already mentioned in the comments just change {{ item.history_type }} to {{ item.get_history_type_display }} in the template.
What is this sorcery and where does it come from?
This is actually vanilla django functionality and is explained in the Model instance reference.
For every field that has choices set, the object will have a get_FOO_display() method, where FOO is the name of the field. This method returns the “human-readable” value of the field.
Why does it work for the history_type field of django-simple-history?
Quite simple: The history_type field has the aforementioned choices set. I checked that by looking at their source code on github.
"history_type": models.CharField(
max_length=1,
choices=(("+", _("Created")), ("~", _("Changed")), ("-", _("Deleted"))),
),
Related
I need to display metafields based on the variants selected on the product page. I want them to change as the variants are clicked. I may need some jquery help but I am not that sure how to apply with liquid. Below is my code, any help is greatly appreciated!
{% for variant in product.variants %}
<div id="tab{{ forloop.index0 }}" class="zr-tabs-panel {% if forloop.first == true %}js-active{% endif %}">
<div class="table-responsive>">
<table class="table table-striped">
<tbody>
{% for field in current_variant.metafields.var_meta %}
<tr>
<td>{{ field | first }}</td>
<td>{{ field | last }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endfor %}
The short answer is that you will need to (a): Expose your meta fields to your site's javascript somehow, then (b): Update your variant-changing code to also update the section based on your meta fields.
In many themes, the variant-changing code is contained in a function named selectCallback (though this isn't the case in all themes - if you have trouble finding this code, you can try reaching out to your theme's developer for theme-specific advice).
Whenever you're using Liquid code to put values into Javascript code, I strongly recommend using the json filter - Liquid's magic filter that ensures your output will always be Javascript-legal. (Quotation marks and line breaks will be properly escaped, empty values will be printed as null, etc)
I have never done any javascript but I saw that this is what I am looking for to display a dynamic table one of my html template.
I have read that there should be something using JQuery but not much more.
So I am looking exactly for an example of dynamic table able to sort rows following which column is selected, written in javascript, displayed in an HTML template, using:
- as columns: the fields of a MySQL table (see example below).
- as rows: the entries contained in the same table
And all of this has to use Django (I don't know if the javascript file either has to be separated from the HTML template or has to be in the HTML template)
Example MySQL table:
CREATE TABLE PDB(
id_PDB_chain CHAR(5) NOT NULL PRIMARY KEY,
id_PDB CHAR(4) NOT NULL,
chaine VARCHAR(10) NOT NULL,
header VARCHAR(255) NOT NULL,
sequence_Proteine TEXT NOT NULL,
start_seq INT NOT NULL,
taille_Proteine INT NOT NULL,
resolution_PDB FLOAT NOT NULL,
meth_Res VARCHAR(10) NOT NULL,
FOREIGN KEY (meth_Res)
REFERENCES methodes_res(meth_Res)
ON DELETE CASCADE
);
Corresponding class in the "models.py" file:
from __future__ import unicode_literals
from django.db import models
class Pdb(models.Model):
id_pdb_chain = models.CharField(db_column='id_PDB_chain', primary_key=True, max_length=5) # Field name made lowercase.
id_pdb = models.CharField(db_column='id_PDB', max_length=4) # Field name made lowercase.
chaine = models.CharField(max_length=10)
header = models.CharField(max_length=255)
sequence_proteine = models.TextField(db_column='sequence_Proteine') # Field name made lowercase.
start_seq = models.IntegerField()
taille_proteine = models.IntegerField(db_column='taille_Proteine') # Field name made lowercase.
resolution_pdb = models.FloatField(db_column='resolution_PDB') # Field name made lowercase.
meth_res = models.ForeignKey('MethodesRes', models.DO_NOTHING, db_column='meth_Res') # Field name made lowercase.
def __unicode__(self):
return self.id_pdb
class Meta:
managed = False
db_table = 'PDB'
In case you need any other informations just ask in comments and I will edit this post with the informations.
In your views.py create a view under whatever name you'd like. Create a list and set it to whatever data you want from your specific model. now go to your template. With that list populated by your specific data you have chosen from the database, use an If statement to check to see if there is anything residing in that list. If there is data there then you can use a For loop like so:
{% for model_name in list_name %}
model_name.model_data etc # Mark it up with relevant html table code, though divs are more preferred
You can mark up the data as needed to display a table, though divs would be more compliant and nicer than tables. This is just a basic example. On the Else statement if no data exists in the list ahead of time, you can simply output that no data exists. Take a look here https://docs.djangoproject.com/en/1.10/intro/tutorial01/
They walk you through building a polling app, where it is relevant to you is the index.html template they build pulling the question data from the database and displaying an unordered list of the questions on the home page as links to vote on. Simply follow this tutorial and look at how they implement the models.py and views.py along with the template and then change the markup from am unordered list to whatever suits your needs.
I found a solution that worked for me and it was really simple in fact:
first you have to download jquery and jquery.tablesorter. Here is the official website where you can download everything and where everything is explained : http://tablesorter.com/docs/
Then, as I work with Django my HTML templates are in a "myapp/templates" directory and my CSS and Javascript files are in a "myapp/static/myapp/" directory.
Here is the template I used:
{% load static %}
<head>
<link rel="stylesheet" type="text/css" href="{% static 'myapp/style.css' %}" />
<script type="text/javascript" src="{% static 'myapp/jquery-3.2.0.min.js' %}">
</script>
<script type="text/javascript" src="{% static 'myapp/jquery.tablesorter.min.js' %}">
</script>
<script type="text/javascript">
$(document).ready(function()
{
$("#pdbtable").tablesorter();
}
);
</script>
</head>
{% if protdb %}
<table id="pdbtable" align="center" border="3" width="100%">
<thead>
<tr>
<th>PDB Id</th>
<th>Chain</th>
<th>Header</th>
<th>Size</th>
<th>Resol.</th>
<th>Method Res.</th>
</tr>
</thead>
<tbody>
{% for i in protdb %}
<tr>
<td>{{ i.id_pdb }}</td>
<td>{{ i.chaine }}</td>
<td>{{ i.header }}</td>
<td>{{ i.taille_proteine }}</td>
<td>{{ i.resolution_pdb }}</td>
<td>{{ i.meth_res }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No PDBs are available.</p>
{% endif %}
And here is my corresponding view:
def pdbinfo(request):
protdb = Pdb.objects.order_by('id_pdb_chain')\
[:len(Pdb.objects.order_by('id_pdb_chain'))]
context = {
'protdb': protdb
}
return render(request, 'pdbapp/pdbinfo.html', context)
As you maybe know, since you are using Django, your template has to receive all informations from a view in views.py and the table of your database (in my case I use MySQL) have to be filled with entries.
This code is working, take some inspiration from it.
One other content that helped me and that gives more details is a youtube video, check the link here: https://www.youtube.com/watch?v=-wAWfPVXlME&t=334s
I hope it will help!
I have a table that will have varying columns over time and I want my django view to support those changing columns. I also want to use ng-repeat to do some fancy stuff with it such as filtering and other things. However I am having trouble combining the two.
I am passing in the arbitrary col_names with django template language. packages is also sent in with the django template language and is essentially a json array where each row is a dict mapping col_name to some value. i.e.
$scope.packages = [{'col1': 'row1col1', 'col2': 'row2val2'}, {'col1': 'row2col1' ....
However when I go to put in the rows using packages I can't "nest" my templates. Is there a way to grab arbitrary values out of each row in `packages?
<input ng-model="search" placeholder="Search">
<table style="width:100%;">
<thead>
<tr>
<th>Permanent Column 1</th>
<th>Permanent Column 2</th>
{# changing columns #}
{% for col_name in col_names %}
<th>{{ col_name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
<tr ng-repeat="package in packages | filter:searchPackage">
{% for col_name in columns %}
<td>{{package.{{ col_name }}}}</td> DOESN'T WORK!
{% endfor %}
</tr>
</tbody>
</table>
In that problem line I essentially want to have {{package.ACTUAL_ARBITRARY_COL_NAME}} but I don't know how to do that programmatically
The problem
By default, Django and AngularJS use the same tokens {{ and }} for templating.
So this gets first processed by Django template
{% for col_name in columns %}
<td>{{package.{{ col_name }}}}</td> DOESN'T WORK!
^ ^
|________________________|
Django template will try to process this value
Because Django tries to expand what's inside the first {{...}}, you will not get what you want AngularJS to see.
If you want to continue down that road, I suggest you read some solutions to this problem here
Better solution
A better approach is to give AngularJS the items you want Django to loop for you.
$scope.columns = [...];
Then use AngularJS to do all the loops. Whichever way you do it, if you need it done in AngularJS, better do it all in AngularJS and not half-Django half-AngularJS.
I am reading a JSON file, accessed via Python. The values from JSON file will be then displayed on a table. Per row, I have a button. What I want is to see the value when I click the button.
What algorithm I could use in such a way that i could store the ALL values so when I click the button, I can get its corresponding ROW value.
Iteration of my JSON file below:
<tr>
<td align="center">{{ entryIteration.sha1 }}</td>
<td align="center">{{ entryIteration.requestedStatus }}</td>
<td align="center">{{ entryIteration.detectionName }}</td>
<td>{{ entryIteration.userRemarks }}</td>
<td>
Approve
Reject
View
</td>
</tr>
{% endfor %}
$('.btn btn-default').click(function(){
var tdtext1 = $(this).closest('tr').find('.tdclass1')
var tdtext2 = $(this).closest('tr').find('.tdclass2')
})
Use .closest() to get the value of data in the row where the button is
Description: For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
In my application results are displaying as a table format.
Part of my code is,
{% for device in devices %}
<tr>
<td>{{ device.operator}}</td>
<td>{{ device.state }}</td>
<td>{{ device.tstampgps }}</td>
<td><button id='rec_delete'>Delete</button></td>
</tr>
{% endfor %}
Even if we press the delete button, I need to delete the particular record from the database. before that I want to prompt a confirmation box for that.
Can anyone help me?
Add a unique record Identifier that you can associate to DB to the button. Once confirmed you send this identifier to server with AJAX and sever code does the DB delete. Also change ID to class on repeating elements since ID's must be unique
HTML
<tr>
<td>{{ device.operator}}</td>
<td>{{ device.state }}</td>
<td>{{ device.tstampgps }}</td>
<td><button class='rec_delete' data-record_id="{{ device.DB_ID }}">Delete</button></td>
</tr>
JS
$('button.rec_delete').click(function(){
/* data() method reads the html5 data attribute from html */
var record_id=$(this).data('record_id');
if( confirm( 'Are you sure') ){
$.post( 'serverPage.php', { id: record_id}, function(){
/* code to run on ajax success*/
$(this).closest('tr').remove();
})
}
})
Server will receive the post key id as you would with any other form element name
Since I don't know Django, this doesn't include the delete part, which I assume you will AJAXify that (do an asynchronous request to delete). I'm also showing the $devices and $deletes variables as local variables here separately, more or less so you can see how you can store references and then work from those references (which I believe is a better practice than reselecting over and over).
Note also the use of:
jQuery(document).ready(function r($){
I'm using jQuery() in the global scope, which in a larger app you should always do to keep from conflicting with other libraries/frameworks which may use $(). This is also a best practice, and you can use $() within that anonymous function (closure). It's best to get used to doing it this way, IMO.
<table>
<thead>
<tr>
<th>Operator</th>
<th>State</th>
<th>T-Stamp GPS</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr class="device">
<td>Verizon</td>
<td>OK</td>
<td>033830928</td>
<td>
<button type="button" id="d001" class="delete">Delete</button>
</td>
</tr>
...
</tbody>
</table>
NOTE
I made a slight but important change, with reference to the $self, since the AJAX will run the success handler after this is out of scope:
jQuery(document).ready(function r($){
var $devices = $('tr.device'),
$deletes = $devices.find('button.delete');
$deletes.click(function d(){
var $self = $(this).parents('tr.device'),
del = confirm('Delete device?');
if (del) {
// Do $.ajax() request, maybe using the
// clicked button's ID. Or you could put
// the row to delete ID on the TR element.
// And then on success of the AJAX, run:
$self.fadeOut(500, function f(){
$self.remove();
});
}
});
});
http://jsfiddle.net/wMqr8/2
You can add a click event to your JavaScript, and if the user chooses the "ok" button, you can send a request to the view that takes care of removing the record or whatever
Try this:
<button id='rec_delete' onclick="return confirm('Are you sure?')">Delete</button>