Plone-like search box in Django? - django

Plone has a beautiful search box with a "Google suggest" like functionality for its site. It even indexes uploaded documents like PDFs. Does anyone know of a module that can provide this kind of functionality in a Django site?

Plone implements it's LiveSearch feature by maintaining a separate metadata table of indexed attributes (fields such as last modified, creator, title are copied from the content objects into this table). Content objects then send ObjectAdded/ObjectModified/ObjectRemoved events, and an event subscriber listens for these events and is responsible for updating the metadata table (in Django events are named signals). Then there is a Browser View exposed at a fixed URL that searches the metadata and returns the appropriate LiveSearch HTML, and finally each HTML page is sent the appropriate JavaScript to handle the autocomplete AJAX functionality to query this view and slot the resulting HTML results into the DOM.
If you want your LiveSearch to query multiple Models/Content Types, you are likely going to need to send your own events and have a subscriber handle them appropriately. This isn't necessary for a smaller data sets or lower traffic sites, where the performance penalty for doing multiple queries for a single search isn't a concern (or you only want to search a single content type) and you can just do several queries from your View.
As for the JavaScript side, you can roll-your-own or use an existing JavaScript library. This is usually called autocomplete in the JS library. There is YUI autocomplete and Scriptaculous autocomplete for starters, and likely lots more JavaScript autocomplete implementations out there. Plone uses KSS for it's JavaScript library, the KSS livesearch plugin is a good place to start if looking for example code to pluck from.
http://pypi.python.org/pypi/kss.plugin.livesearch
And a tutorial on using KSS with Django:
http://kssproject.org/docs/tutorial/kss-in-django-with-kss-django-application
KSS is quite nice since it cleanly separates behaviour from content on the client side (without needing to write JavaScript), but Scriptaculous is conceptually a little simpler and has somewhat better documentation (http://github.com/madrobby/scriptaculous/wikis/ajax-autocompleter).

Related

Django - Is it possible to show loader until a start page is loaded?

My view function takes a long time until returning a template. So, I'd like to show something to a user while running the function.
Is it possible to show loader until a start page is loaded?
What's important is the loader should be shown when loading the first page after first visit of a user?
Thank you for reading my question.
You would have to fetch the page using JS. You could use something like Intercooler or PJAX which provides HTML attributes that show a spinning animation while loading the content via AJAX.
A better solution would be to make your page faster. There are several things you should consider:
Check that all Model fields that you are using for filtering or sorting have set db_index=True unless the tables are small (few hundred entries) or the fields are already unique or foreign/primary keys. Also check that your DB does sorting and merging in RAM not on disk (== the DB has enough RAM resources and has also the correct configuration to use it).
Sometimes, if you show a list of model instances you end up making separate DB requests per row if you access related models in your template. Again, check which statements your DB executes and have a look at Django's select_related, prefetch_related, values and values_list methods that can dramatically increase lookup performance. Make sure your template context contains all necessary data and only the necessary data (e.g. pageing, how much, or maybe you should consider a search index like SOLR or Elastic which can be integrated nicely via Django Haystack).
Load everything except heavy data at once in your main view, which also includes JS. The JS then uses AJAX to load the rest from a second Django view which returns an HTML snippet that your JS simply adds to the DOM.
It really depends on how comfortable you are with JS and how much you want to stick to HTML to make as much use of Django as possible (thinking of Django Forms for example). But first, tune your DB setup (disclaimer: I have written that article).
it's better to make a request with javascript to your Django endpoint, until you get a response back from your server you should show your loader, and when you get the response back successfully you should make display: none for loader and mak display: block for your loaded content
Create a function in views.py and send JsonResponse. URL example: http://localhost:8000/somedata
Render any other HTMLlet's say it's index.html. URL example: http://localhost:8000/home
That index.html file need to have some JavaScript, let's say main.js
In main.js make a request to http://localhost:8000/somedata and fetch data. Use async javascript that way you can easily track fetched data or not

Applying Javascript MVC architecture on existing backend MVC

We currently have a large implementation done in Django which mostly spit out static HTML. We are planning to implement a javascript modular framework to hook to django's API and define needed routes..etc
But, we do not want to scratch off what we did so far as the site is completely functional for non-js users. The more I read about JavaScript MVC designs, the more I find it impossible to implement the two to work together.
Any ideas of how to proceed in that direction? is there a best practice that someone can follow?
Keep what you got right now as a fail-safe. Create new, separate views meant for Ajax requests that handle the processing of data and respond with appropriately formatted respond data (XML, JSON etc.).
Basically, Django is your model. Any action defined by your Javascript controller can either modify the model or the view.
If it modifies the view, there are two options: you either change just the display of data, and thus you just call a Javascript function that alters the HTML, or you display new data. In that case, you have to create a Django view that supplies that data in a format that Javascript can process easily. In your Ajax request, supply a callback (the view part of your Javascript) that handles displaying that data.
If the action modifies the model, you also need to create a Django view that processes the POST data sent by the Ajax request as needed, and returns either the error messages or a success message in a format that is, again, easily processed by Javascript. Again, you should register a callback to your Ajax request that handles the display of the messages returned by Django.
So basically, the only change to your current views would be that you supply the appropriate Javascript code to map the actions to Ajax requests and to handle the data returned by Django for your Ajax requests. Everything else should be done in separate Django views.

User controlled presentation of data in widgets on a dashboard app - Best Practices?

Consider a very simple dashboard application in Django. It has 2 models:
Page
Widget
Naturally, Page and Widget have a ManyToMany relationship.
Like any good dashboard implementation, the designers can change 3 things in a widget:
Data source that drives the widget
Placement of widget on the Page
Presentation of Data inside a widget
The Data is specified using a URL field in the Widget and is being served by a REST API based on Django REST Framework with the django-filter backend.
The Placement on the Page is catered using the excellent Gridster.
This leaves the Presentation part. I have two possible solutions:
Attach a template TextField with the Widget. Data will be fetched from web services in JSON format and rendered according to the template (handlebars) defined in Widget on the client side.
Pass the template name as query string in the URL to the REST API and render the Data using the user-specified template.
Now that the context is clearly defined (hopefully), following are my questions:
Is there any way I can choose the first solution and still be able to use the automatic forms generated by the DRF Serializers?
If not, and I choose the second solution, are there any potential pit-falls regarding security, code maintenance, code quality, testing and the like? Why have I not seen anyone else doing this i.e. letting the user select the template via query string?
Is there any other solution that I am missing?
Your first options seems most promising: fetch the data as JSON and insert it into templates on the client. All good.
So can you do that "and still be able to use the automatic forms generated by the DRF Serializers"? — Short answer, it depends what you mean by "automatic forms".
Serializers take a data dictionary, validate it and (for ModelSerializer subclasses) convert it into a (model) object instance for you. If by "automatic forms" you mean will you still be able to this validation behaviour, then the answer is yes. Create your JSON payload on the client and send an appropriate HTTP request to the API. Django Rest Framework's Serializers will work as expected.
If (though) by "automatic forms" you mean will you still be able to use the HTML forms that DRF provides in its web broweasble API, then the answer is no. The browseable API is built around an HTML renderer returning entire web pages. These include a pretty-printed representation of the JSON you'll be using as well as the web-forms that, on this assumption, you're interested in.
If you go this route you'll need to generate the forms on the client, using whatever model, view, template and binding features your chosen library (libraries?) offer(s).
I hope that helps. Good luck.

How to prevent Django pages from refreshing after submit?

I am using the Django template system. What I want is, when I submit a form, or click to an url link, page does not refreshes, but loads with the data returning from the server. Is it possible?
I recommend a combination of jQuery (easy, powerful, popular javascript library) and dajax/dajaxice (http://www.dajaxproject.com/). Dajax is very easy to set up and use, and jQuery is also easy to set up and use. Dajax is strictly for AJAX communications through Django. jQuery is perfect for taking a simple site and making it more fluid, intuitive, and user-friendly.
You need JavaScript to do that. What you are looking for is called AJAX (Asynchronous JavaScript and XML). Essentially, it means you use JavaScript to send a request to the server as soon as the link/button is clicked. The server returns some data to your Script, which then can be used to manipulate the HTML page, e.g. by inserting the responded data into the DOM. Since you do everything with JavaScript, no reloading of the whole page is required.
To start, read the AJAX tutorial. There are certain JavaScript libraries that make these things more simple for you (e.g. jQuery), but you really should understand how this stuff works first, since else you might get into trubble while trying to debug it.

Pass array from HTML to Django application

I developed an application in JSPs and Servlets involving drop down menus that kept growing with how many authors per publication their were.
This was done in JavaScript and then in my application iterated through them using a loop. Is this possible using Django? This would be useful in my application.
This link might help you out if you don't want to dive into javascript (too much)
http://www.dajaxproject.com/
Or have a look at this stackoverflow question/awnser:
What is the best AJAX library for Django?
In any case, you need to serialize your array to a JSON string.
Then pass the JSON with an XMLHTTPRequest (ajax) to the server.
Add the javascript tag to your question if you don't mind more JS solutions.
Otherwise look for a Django Ajax framework to do the heavy lifting for you.