Django retrieve data from database to template - mysql

I have a problem on retrieving the data from database,
I'm using Mysql database and one table which contains 15 fields which I'm going to display it on template in a table.
It has more than 4 million records in the table,
def index(request):
args = {}
data = Mymodel.objects.all()
args['data'] = data
return render(request, 'index.html', args)
I tried this way but the data loads very very slowly,
and next approach I tried for database connections
def index(request):
args = {}
sql = "select * from mymodel"
cursor = connection.cursor()
cursor.execute(sql)
result = cursor.fetchall()
args['result'] = result
return render(request, 'index.html', args)
This also does the same, I need to load the data much faster. Please suggest to me any approach that would load the data faster.

One concept correction before the solution is that using raw sql doesn't do any better than django ORM and you also lost the ability to use ORM api to display the data easily.
The common solution is to use django built in pagination to show only certain amount of records per page. Django doc has very detailed explanation about the usage of pagination.

Since you're already executing a raw query, I don't think you'll be realistically able to do much better than what you have.
Is there any reason why you can't paginate the results? Normally you never return all the data available.
You can try and use a QuerySet.iterator to avoid having to load all your instances in memory at once. Also, QuerySet.values would return dictionaries instead of full-blown model instances, reducing memory usage.
If you absolutely need to and you get into request timeouts, one option is to run the actual data retrieval in the background. For example, you could use Celery and run the query as part of a task. Your view would trigger the Celery task and return a task identifier in the response. The consumer could then poll a "job status" endpoint passing such task id and retrieve the results when they are ready. You'd still need to store the results somewhere else (faster) than your db, i.e. Redis (which you can easily use as a Celery backend).
This approach is obviously more convoluted and would add a few moving parts to your system and you're likely to get into other issues anyway (e.g. the response size). Using pagination if possible would be a lot easier.

You can use pagination if you want your system to work for thousands of records. Django genaric ListView will help you in this case. They are easy to use. They works like this
class YourView(ListView):
template_name = 'books/acme_list.html'
context_object_name = 'object_list'
queryset = TableName.objects.all()
paginate_by = 50
Your template will be like this
<table id="exam">
{% for object in object_list %}
<tr>
<td>{{ object }}</td>
</tr>
{% endfor %}
</table>
And your paginate section will be like this
{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li>
<span>Previous</span>
</li>
{% endif %}
<li class="">
<span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
</li>
{% if page_obj.has_next %}
<li>
<span>Next</span>
</li>
{% endif %}
</ul>
{% endif %}
You can find further detail in this link and Django documentation.

Related

how to perform mathematical operations in django template

i want to print the value of current item in list(which is a integer) and its successor(not the list item) but the actual integer successor) at the same time..i am using
{% for i in hour %}{{ i }}-{{i+1}}{% endfor %}
but this gives me an error of "Could not parse the remainder: '+1' from 'i+1'"
Try: {{ i }}-{{ i|add:"1" }}
See https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#add
As far as I know there are three approaches:
Change to a different templating language that allows cleaner logic (Mako I believe though my knowledge is out of date)
Install a third party django package that allows you to do math in templates.
Create a template tag that accepts a value (i), does the calculation you want, and returns that value.
#3 is the one I would suggest.

How to access `site.data.header["foo.bar.baz"]` if `foo.bar.baz` is a FrontMatter variable

I want something like:
---
my_var: "foo.bar.baz"
---
{{- site.data.header[page.my_var] -}}
Unfortunately, it doesn't work…
I know that I can use site.data.header.foo.bar.bazor site.data.header["foo"]["bar"]["baz"], but it's not that.
Also I know that I can split page.my_var to substrings and use them then as site.data.header["foo"]["bar"]["baz"]. But this increases Jekyll build time.
I guess I need some Ruby plugin, but don't know one and I don't know Ruby to write one.
If you know such plugin or can help me write one or know some native workaround, this would be sooo great!
Help :)
Also I know that I can split page.my_var to substrings and use them then as site.data["foo"]["bar"]["baz"]. But this increases Jekyll build time.
I'm not sure you can do this. And even if you can, I'm not sure that there is a real performance impact.
But you can do this :
_data/foo.yml
bar:
baz: 1
biz: 2
buz: 3
beer:
baz: 1
biz: 2
buz: 3
Then :
---
my_var: "foo.bar.baz"
---
{% assign keys = page.my_var | split: "." %}
{% assign object = site.data %}
{% for key in keys %}
{% assign object = object[key] %}
{% endfor %}
{{ object }}
What are hoping to do has been blocked by design.
site.data["foo.bar.baz"] implies that you need to have a data file named foo.bar.baz.yml or foo.bar.baz.json, ... etc.
But Jekyll sanitizes data files' names and therefore the resulting object would only have a key named "foobarbaz"
A plugin that purposely removes this sanitization can written but it wouldn't appear to be a benign or safe to end-users. So the chances of finding such a plugin in the wild is slim..

Jekyll Nested Data

I have a nested yaml data file for my jekyll blog like so:
Nickname1:
name: John
address: Johnstreet 1
Nickname2:
name: Rudolf
address: Rudolfstreet 1
I use this to print additional information after each post, which I specify in the front matter. This works fine.
I now wish to create a site that lists all entries of this data file. This should in theory be easy:
{% for nickname in site.data.NAMEOFFILE %}
<li> {{ nickname.address }} </li>
{% endfor %}
However, this does not work because the YAML data is nested. The data has to remain nested, and each entry needs to have a different nickname. The problem with that is of course that I am unable to loop over all entries, because they are all differently named.
Can you folks help me out here? Is there any way in which I can achieve this without changing the nested structure of my data file? Changing the nested structure would break large parts of my site.
Jekyll data files can be set up in two formats: list or dictionary (not the official terminology, but that's what I call them and what helps me understand them).
Lists are used for iteration. Dictionaries are used for looking up an individual item and shouldn't be used in iteration.
// list.yml
- nickname: Nickname1
name: John
address: Johnstreet 1
- nickname: Nickname2
name: Rudolf
address: Rudolfstreet 1
...
// usage
{% for person in site.data.list %}
<li> {{ person.address }} </li>
{% endfor %}
// dictionary.yml
Nickname1:
name: John
address: Johnstreet 1
Nickname2:
name: Rudolf
address: Rudolfstreet 1
...
// usage
{% assign person = site.data.dictionary['Nickname1'] %}
<ul>
<li> {{ person.address }} </li>
</ul>
I have the same data in two different files: one in a list format and one in a dictionary format. That lets me iterate or do specific lookups whenever I need. Drawbacks are that you have duplicated data across two different files and need to maintain consistency whenever you make changes.
To solve your specific problem, I would make another data file with the data formatted into a list so that you can iterate through the data. This means you don't need to change the file with the nested structure and can avoid breaking the site.
Jekyll docs example on 'dictionary' usage
Jekyll docs example on 'list' usage
When you iterate over an object, the iteration variable is a two-element array with the key at index 0 and the value at index 1:
<ul>
{% for nickname in site.data.people -%}
<li>
{{ nickname[0] }}: name {{ nickname[1].name }},
address {{ nickname[1].address }}
</li>
{% endfor %}
</ul>
renders (after whitespace cleanup) as
<ul>
<li>Nickname1: name John, address Johnstreet 1</li>
<li>Nickname2: name Rudolf, address Rudolfstreet 1</li>
</ul>
Weirdly, I can't find this described anywhere in the Liquid docs, neither on the Jekyll site nor in the official documentation. The only reference I've seen is on the platformOS documentation page.

can I use ajax datatable in Django with runtime custom query

I really want to use datatable for big data with runtime custom query .I have tried django-datatable but seem , it have only static custom query. thanks
I took a quick look at django-datatable; the only thing it seems to do if provide a template tag to render entire DB tables to HTML responses.
{% load table_tags %}
...
{% render_table people %}
If you want custom DB queries in django, the normal way is to use the ORM, i.e.
#!/usr/bin/env python
from models import Person
from django.shortcuts import render_to_response
...
def some_view(...):
a_people = Person.objects.filter(name__startswith="A")
return render_to_response(<template>, context={"people":a_people})
// HTML template
...
{% for person in people %}
<tr><td>{{ person.id }}</td><td>{{ person.name }</td></tr>
{% endfor %}
...
This allows you all freedom to define a dynamic DB query in your python code.

How to adjust Jekyll post order?

I have started a Jekyll based blog with a theme jekyll-now. I am new to Jekyll and how it operates (especially Liquid). I understand that new posts need to be as follows: 2014-10-04-Hello-World.md. But I really don't understand how I could order these.
My first thought is that they order by date so two posts on the same date would order randomly. But is this not the case? Is there a way of ordering posts chronologically. OR at least having a post archive page?
There is an example in the official Jekyll documentation how to create a basic post archive page:
Displaying an index of posts
Bonus: For a prettier archive page (grouped by year or year/month), see this answer.
You're right, I can't find anything in the docs where it says how the posts are ordered, but in fact Jekyll does order them chronologically, with the most recent post first (you can see this if you try the examples I linked above).
To sort them the other way (the oldest post first), you can use the reversed keyword, according to the Liquid documentation:
{% for post in site.posts reversed %}
However, I don't know how two posts on the same date are ordered, because I don't write that much posts, so I never had that problem :-)
You have to try that yourself.
Just faced the same problem and solved with this solution:
https://groups.google.com/forum/#!topic/jekyll-rb/8QCIzevauSU
Add a date field to the YAML Front Matter of a post, like so:
date: 2010-09-15 14:40:45
e.g. if you have 2 posts on 2014/12/31, you can add date: 2014-12-31 00:30:00 to latest_post.md, and date: 2014-12-31 00:10:00 to older_post.md.
You can add time zone (e.g. date: 2014-12-31 00:10:00 +08:00) if needed
I want to document my struggle into this post so it may help other users. You need to do two changes:
Open your posts and add weight. e.g., weight:100
Open your html file for the menu where you want the sorted posts. For Java/J2EE menu I have java.html file at the root path of my project.
Then, add the {% assign pages_list = pages_list | sort:"weight" %} line as shown in the below code. This will sort by weight.
{% for category in site.categories %}
{% if category[0] contains 'java' %}
<h3 id="{{ category[0] }}-ref">{{ category[0] | join: "/" }}</h3>
<ul>
{% assign pages_list = category[1] %}
{% assign pages_list = pages_list | sort:"weight" %}
{% include JB/pages_list %}
</ul>
{% endif %}
{% endfor %}
Jekyll just string-compares post paths when sorting, which is why the date format is year-month-day. Posts are internally also collections and you can see the sorting being invoked in reader.rb:
# Sorts posts, pages, and static files.
def sort_files!
site.collections.each_value { |c| c.docs.sort! }
site.pages.sort_by!(&:name)
site.static_files.sort_by!(&:relative_path)
end
So it's using generic ruby methods to sort and implements the comparator in document.rb:
# Compare this document against another document.
# Comparison is a comparison between the 2 paths of the documents.
#
# Returns -1, 0, +1 or nil depending on whether this doc's path is less than,
# equal or greater than the other doc's path. See String#<=> for more details.
def <=>(other)
return nil unless other.respond_to?(:data)
cmp = data["date"] <=> other.data["date"]
cmp = path <=> other.path if cmp.nil? || cmp.zero?
cmp
end
Which means it first compares the dates and only checks the text if needed.
The date is special only if it somehow wasn't found (no metadata). For drafts it falls back to the file modification time, for the rest to the site time.
So if you want to force a different ordering of posts from the same day, craft the start of the title in the filename to alphabetically sort first. Eg. 2020-01-01-a.md will come after 2020-01-01-b.md if you're listing posts in descending order.