Textbox warning for large queries with Django - python

I'm using Django to create a website for a project. The user fills out a form, then I run some queries with this data and display the results on another page. Currently it's a two page site.
I want to warn the user if their query result data is very large. Say if a user ends up getting 1000 rows in the results table, I want to warn the user that queries of this size might take a long time to load. I imagine that between the form page and the results page, I could make a popup textbox that displays the warning. I could have this box show if the query object size is greater than 1000.
Does Django have a method for me implementing this? How can I get this textbox to appear before the result page template is shown?

Yes, query object has the method like this. It is simply:
query.count()

No, I don't think django has a function that will do this. You could easily do this, if you wanted to, using django and javascript though.
Loading a site with 1000 results really isn't that many. If the number of results is affecting performance, paginate them.
I think it might be a bit cleaner to just load the results page, directly, with either:
paginated results
no results and have an ajax request fetch results after the page is loaded, so the page doesn't lag while loading all results
What will your user think of an intermediarary popup? I belive to maximize their expereince, load the page in the fastest least intrusive way possible

Related

Django-tables2, Django-filters how to override .empty_text

Hope everyone is well.
I'm using django-tables2 and django-filters to display large datasets in html tables.
I wanted to use the django-tables empty_text to return a message when there is zero results.
However I currently load the tables with an empty queryset to avoid large load times (Better to let the user decide if they want to generate the whole data set), this causes a problem because the empty_text message populates.
I want to know if there is a away to stop the empty_text message appearing if there is no filters applied or no filter URL.
If I can't do it that way maybe there is a better way to determine empty set on filter result.
Thanks in advance,
Thomas

Wait for datastore changes before redirecting

Very similar to this question, except that the answer is not suitable.
I populate a table from a datastore query, then there is a link allowing the user to delete a specific row. Clicking the link goes to a url that deletes the row from the datastore then redirects back to the table.
Changes more often than not aren't shown in the table until reloading again.
Easy solution is to redirect to another page, that uses a javascript redirect to add a delay of a couple of seconds. Other alternative is to send details back to the page like action=delete&key=### and then make sure that item is missed from the table. That's a pain though.
The answer is with ancestor queries.
https://cloud.google.com/appengine/docs/python/datastore/queries#Python_Ancestor_queries
Create the entities with a parent. When one of the entities is deleted, you can run an ancestor query for your table list view which will have strong consistency when data is changed.
Example ancestor query:
tom = Person(key_name='Tom')
photo_query = Photo.all()
photo_query.ancestor(tom)
With the datastore, unless you can use ancestors, you cant guarantee when the indexes will be updated, only the entity itself (for getting by key later) by doing a put without async. Best is a combination of your suggestion where the client takes into account its action to patch the ui, plus maybe using memcache to remember recent actions and patch queries server-side before returning to client.
Here is a different approach. Use Javascript and AJAX. When the user clicks a link, you do two things:
Use Javascript/jQuery to remove the row from the DOM, and
Send an AJAX call to the server to do the appropriate datastore modifications.
It makes for a nice user experience because you are not reloading the page at all.
You might want to consider that there is always room for displaying outdated info in the table: for example displaying the table simultaneously in 2 different windows/tabs, then in one of them deletion is performed, the other will still display a delete link which will cause a 404 if followed.
With this in mind I'd 1st focus on managing the expectations (the user should know that the page may occasionally display outdated info) and then on the user's ability to get an outdated page in sync (refresh button?). Which might make the issue moot.
The delay-based "solutions" are bound to fail sooner or later in race condition scenarios, I wouldn't bother with the extra complexity. Especially for the document where the deletion is done: that's exactly where the user knows that the info is outdated (for free) and would be likely inclined to refresh until the recent change becomes visible.

What's the easiest way to display large queries using the Django frame work?

I am working on an internal database that a handful of people will be using to access. In short there will be a non-authenticated search page that will allow them to do partial searched on various fields.
I am trying to figure out the best way to display upwards of 1000 individual components. Ideally it would show a list of N components on a page. But since I do not know the size of the query until they press search I don't know how to split it up.
I am fearful this is a case of I don't what I don't know.
I think you want Django's pagination. That should allow you to query a database, and split the resulting objects across pages. It even has an example.

Does Comet(long polling) needed for Django activity stream

Does anyone has idea how to display django stream actions on templates.
Does I need to use Comet to fetch values to display on my template. Since, When I am doing action.send, it is storing verb and description in table actstream_action. But how should I display the values on template ?
P.S. Please note that this is first time I am using django-activity stream.
I've checked django-activity-stream, seems it has no magic for rendering activity updating dynamically.
Check django-socketio for websockets way. Or simply polling tech would satisfy your requirement if the expected access loading is not that high.
I'm not quite sure what you mean about "fetch actions directly to template using various templatetags" because template rendering is accomplished during request-response proceduret.

How to optimize for Django's paginator module

I have a question about how Django's paginator module works and how to optimize it. I have a list of around 300 items from information that I get from different APIs on the internet. I am using Django's paginator module to display the list for my visitors, 10 items at a time. The pagination does not work as well as I want it to. It seems that the paginator has to get all 300 items before pulling out the ten that need to be displayed each time the page is changed. For example, if there are 30 pages, then going to page 2 requires my website to query the APIs again, put all the information in a list, and then access the ten that the visitor's browser requests. I do not want to keep querying the APIs for the same information that I already have on each page turn.
Right now, my views has a function that looks at the get request and queries the APIs for information based on the query. Then it puts all that information into a list and passes it onto the template file. So, this function always loads whenever someone turns the page, resulting in querying the APIs again.
How should I fix this?
Thank you for your help.
The paginator will in this case need the full list in order to do its job.
My advice would be to update a cache of the feeds at a regular interval, and then use that cache as the input to the paginator module. Doing an intensive or length task on each and every request is always a bad idea. If not for the page load times the user will experience, think of the vulnerability of your server to attack.
You may want to check out Django's low level cache API which would allow you to store the feed result in a globally accessible place under a key, which you can later use to retrieve the cache and paginate for each page request.
ORM's do not load data until the row is selected:
query_results = Foo(id=1) # No sql executed yet, just stored.
foo = query_results[0] # now it fires
or
for foo in query_results:
foo.bar() # sql fires
If you are using a custom data source that is loading results on initialization then the pagination will not work as expected since all feeds will be fetched at once. You may want to subclass __getitem__ or __iter__ to do the actual fetch. It will then coincide with the way Django expects the results to be loaded.
Pagination is going to need to know how many results there are to do things like has_next(). In sql it is usually inexpensive to get a count(*) with an index. So you would also, want to have know how many results there would be (or maybe just estimate if it too expensive to know exactly).

Categories

Resources