I am using ajax to sort the data which came from search results.
Now I am wondering whether it is possible to render just some part of html so that i can load this way:
$('#result').html(' ').load('/sort/?sortid=' + sortid);
I am doing this but I am getting the whole html page as response and it is appending the whole html page to the existing page which is terrible.
this is my views.py
def sort(request):
sortid = request.GET.get('sortid')
ratings = Bewertung.objects.order_by(sortid)
locations = Location.objects.filter(locations_bewertung__in=ratings)
return render_to_response('result-page.html',{'locs':locations},context_instance=RequestContext(request))
how can I render only that <div id="result"> </div> from my view function? or what am I doing here wrong?
From what I understand you want to treat the same view in a different way if you receive an ajax request.
I would suggest splitting your result-page.html into two templates, one that contains only the div that you want, and one that contains everything else and includes the other template (see django's include tag).
In your view then you can do something like the following:
def sort(request):
sortid = request.GET.get('sortid')
ratings = Bewertung.objects.order_by(sortid)
locations = Location.objects.filter(locations_bewertung__in=ratings)
if request.is_ajax():
template = 'partial-results.html'
else:
template = 'result-page.html'
return render_to_response(template, {'locs':locations},context_instance=RequestContext(request))
results-page.html:
<html>
<div> blah blah</div>
<div id="results">
{% include "partial-results.html" %}
</div>
<div> some more stuff </div>
</html>
partial-results.html:
{% for location in locs %}
{{ location }}
{% endfor %}
Related
I am making my app in which I'm querying my data base with like search and what I wanna do is to highlight the results which are showing in my result template. My search route looks like this:
#app.route("/post")
def post():
term = request.args.get("search_text", None)
if term == None:
scanned = Images.query.filter_by().all()[0:15]
return render_template('post.html', scanned=scanned)
else:
term = request.args.get("search_text")
search = "%{}%".format(term)
scanned = Images.query.filter(or_(Images.content.like(search),Images.title.like(search)))
return render_template('post.html', scanned=scanned)
this my template file post.html
{% for scanned in scanned %}
<div class="post-preview">
<a href="/post2/{{scanned.Slug}}">
<h2 class="post-title">{{ scanned.title }}
</h2>
</a>
<p class="Images-meta">Posted by
Admin
on {{scanned.Date}}</p>
</div>
{{scanned.content[0:120]}}...
<hr>
</li></a>
{% endfor %}
now everything is working fine but I just want to highlight my search query in results template.
You write the template 'post.html'. You need to modify that html file to change how things are displayed.
I've been trying to figure this out for days and was unable to find any useful information online.
What I am trying to do is paginate objects from my model after filtering them using a drop down menu and supplying the data to python via AJAX. I know where the problem is but I am not sure how to solve it. I have two templates, first one is:
entry_index.html:
{% extends 'main/base.html' %}
<form action="" method="get" accept-charset="utf-8">
<select class="selectpicker" name="times" onchange="FilterCategories()" id="times">
<option value="1">last 24 hours</option>
<option value="30">past month</option>
<option value="365">past year</option>
<option value="10000">all time</option>
</select>
</form>
<ul id="all-games" class="list-unstyled">
{% include page_template %}
</ul>
The template that is being included in the above template is entry_index_page.html:
{% if objects %}
{% for object in objects %}
do something
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if objects.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ objects.number }} of {{ objects.paginator.num_pages }}.
</span>
{% if objects.has_next %}
next
{% endif %}
</span>
</div>
urls.py:
url(r'^$', views.entry_index, name='index')
views.py:
def entry_index(
request,
template='entry_index.html',
page_template='entry_index_page.html'):
date_from = timezone.now() - timezone.timedelta(days=1)
obj_list=Object.objects.filter(submitted__gte = date_from).order_by('-votes')
message=[]
context = {
'objects': obj_list,
'page_template': page_template}
if request.is_ajax():
template = page_template
message = []
if request.method == "GET":
time_range = request.GET.get('time_range')
if time_range is not None and time_range != u"":
time_range = request.GET['time_range']
date_from = timezone.now() - timezone.timedelta(days=int(time_range))
obj_list= Object.objects.filter.filter(submitted__gte=date_from)
paginator = Paginator(obj_list, 2)
page = request.GET.get('page')
try:
objects= paginator.page(page)
except PageNotAnInteger:
objects= paginator.page(1)
except EmptyPage:
objects= paginator.page(paginator.num_pages)
context.update({"message":message,"objects":objects})
return render_to_response(
template, context, context_instance=RequestContext(request))
ajax.js:
function FilterCategories() {
var timePosted = document.getElementById('times');
$.ajax({
type: "GET",
url: "",
data: {
'time_range': timePosted.value,
'csrfmiddlewaretoken': $("input[csrfmiddlewaretoken]").val()
},
success: filterResults,
dataType: 'html'
});
}
Now to explain what I think is going on and hopefully someone can help me find a solution.
When the home page is loaded (entry_index.html) the model gets filtered based on the first option in the drop down menu (i.e. value="1", which is filtering for the data entries submitted within the last day). The obj_list variable gets populated and is passed to the paginator and everything works as expected. I get a certain number of pages and can navigate through pages. Now lets assume we are on the home page again and I select "all time" from the drop down menu. This will trigger the onchange callback and it will call the FilterCategories() function. Note the url in AJAX is "" (an empty string, so pointing to my index page). According to urls.py, it will call my entry_index() view. Because request is ajax, the template used will change (page_template becomes the new template, page_template = entry_index_page.html). Because the new time range specified with the drop down menu and passed on with ajax, I get a new obj_list which is then paginated and produces "objects" which are then passed as context onto the template. Up until this point everything works as expected. I get right amount of pages etc. However, the problem starts when I try to go to the next page with the newly selected filter. When I click the next page button, the request that is being made is not an ajax request so everything that is in the request.is_ajax() conditional is not executed. So in another words a click to the next page is calling my entry_index view again and the template being used this time around is entry_index.html and my filter is reset back to the default, which is the "last 24 hours" filter. Therefore, when I click the next page what I end up getting is actually the default home page again instead of getting the next page of objects with my newly selected drop down filter.
My question is, is there an easy way to fix this so that I can scroll through the pages of my filtered model? Or should I completely abandon this approach and there is an easier way to do this? I apologize for a long post and I hope someone out there will be able to help me out. Thank you for taking your time to read this.
Here's an example of an approach I've taken to having dynamic content displayed on a page using Django and Ajax:
I was tooling a little browser Sci-fi game just to practice this specific technique. Everything took place in a single view:
class GameViewport(TemplateView):
template_name = "game_viewport.html"
#cached_property
def slug(self):
return self.kwargs['slug']
#cached_property
def game(self):
return Game.objects.get(url=self.kwargs['slug'])
#cached_property
def player(self):
return Player.objects.get(game=self.game)
#cached_property
def current_planet(self):
return self.player.current_planet
#cached_property
def left_column(self):
player = self.player
if player.current_location:
node = player.current_node
if len(Location.objects.filter(node=node)) == 0:
spawn_locations(node)
locations = Location.objects.filter(node=node)
else:
locations = Location.objects.filter(planet=node)
html = "Other Sites in ".format(str(node))
for location in locations:
html += '<li>{} ({})</li>'.format(location.name, location.type.name)
return html
elif player.current_node:
planet = player.current_planet
if len(Node.objects.filter(planet=planet)) == 0:
spawn_nodes(planet, get_name_choices())
nodes = Node.objects.filter(planet=planet)
else:
nodes = Node.objects.filter(planet=planet)
html = '<h4><b>Other Starports on {}:</b></h4>'.format(planet.name)
for node in nodes:
html += '<li> {} ({})</li>'.format(node.name, node.type.name)
return html
elif player.current_planet:
system = player.current_system
html = '<h4><b>Known Planets in {}:</b></h4>'.format(system.name)
for known_planet in player.known_planets.filter(solar_system=system):
html += '<li> {} ({})</li>'.format(
known_planet.name,
known_planet.classification.name
)
return html
else:
html = '<h4><bShip Status</b></h4>'
html += '<p><b>Fuel:</b> 100%</p>'
return html
So as you can see, the left column would generate different html data based on what the player's current settings are. This would be plugged into the template like so:
<div class="col-md-3">
<div class="leftColumn">
{% autoescape off %}
{{ view.left_column }}
{% endautoescape %}
</div>
</div>
If the user clicked on a new location, I would send her decision through AJAX:
$(".planetChoice").click(function(){
event.preventDefault();
var submission_data = {planet: $(this).text()};
console.log(submission_data);
$.ajax({
url: $('#visitPlanet').attr('href'),
type: 'GET',
dataType: "json",
data: submission_data,
success: function(html_data) {
window.location.reload();
},
failure: function(data) {
alert('Something went wrong. Please refresh the page.');
}
});
});
All this would do is update the player's state and reload the page according to her new settings:
def visit_planet(request, slug):
player = Game.objects.get(url=slug).player_1
planet = Planet.objects.get(name=request.GET.get('planet', "").strip())
if planet:
player.current_location = None
player.current_node = None
player.current_planet = planet
player.save()
response = {'status': 1, 'message': "Ok"}
return JsonResponse(response)
Thus displaying the new data, as determined by the left_column property.
I went about this by changing the state in the database, but it could just as easily be accomplished with session variables. I found it to be a relatively clean and DRY way of cycling dynamic content. It also has the advantage of giving Django an opportunity to generate or modify data in between clicks.
Not sure if this applies to your situation, but hopefully it sparks an idea!
EDIT: You don't even necessarily need to output HTML. Here's an approach I am using in a different application:
<!--Product Tile #1-->
{% if view.tile_data.0 %}
<div class="col-md-4">
<div class="card hoverable">
<!--Card content-->
<div class="card-block" id="tile_{{ view.tile_data.0.invoice }}_id">
<!--Title-->
<h4 class="card-title">Shipment {{ view.tile_data.0.invoice }}</h4>
<!--Text-->
<p class="card-text">{{ view.tile_data.0.supplier.name }}
<br>
<b>{{ view.tile_data.0.lbs|floatformat }} Lbs # {{ view.tile_data.0.price }} USD</b>
<br>
{{ view.tile_data.0.variety.commodity }} {{ view.tile_data.0.variety }} {{ view.tile_data.0.inshell|shell_display }}</p>
</div>
<!--/.Card content-->
</div>
</div>
{% endif %}
<!--./Product Tile #1-->
This data is directly fed through the view from a model manager:
def tile_data(self, status, first, last):
return self.model.objects.filter(status=status)[first:last]
In my Django-template:
<div class="A">
{% url renders_data object.id %}
</div>
<div class="B">
{% render_data object.id %}
</div>
Div A is common way to call a method in views.py whereas Div B is for template tags.
User will open a link. Let's say: /myapp/test/ a page will open contain two template tag section at the page. Name of this tag is render_data I want to load the data into each template tag with Ajax. To work with it we need request.ajax:. That is why i thought to write views method. I thought to complete it with the following way:
I wrote the exact copy of template tag in views.py (renders_data with passing object_id parameter) and render it to the right template. When i open the maypp/test after removing the div A from template. It shows the URL (myapp/test/<object_id>) in each template tags section (each corner) except the data. Is their any possibility to show the context except this URL See the image when i choose this option
Second i also thought to import views method (renders_data) in template tag (render_data). So that data will display in each corner and request.Ajax: will also work. if this can be possible then how?
I am not able to solve this issue. please help me :(
See how the render_data looks like:
#register.simple_tag
def render_widget(object_id):
from myapp.plugins.model import Widgetsetting
widget_setting = Widetsetting.objects.get(id = object_id)
widget = widget_settings.get_widget()
template_name = widget.template_name
context = widget.context(widget=widget_settings)
t = get_template("widgets/%s" % template_name)
return t.render(Context(context))
From the code you've posted something like below should work...
in views.py:
from django.http import HttpResponse
from netadmin.plugins.templatetags.widgets import render_widget
def ajax_render_data(request, object_id):
return HttpResponse(render_widget(object_id))
in your django template:
(you said you want several of these on the page, so I'm going to use a loop in the django template, I don't know what your widget collection is called but I'm sure you can work it out for your particular case)
<div class="widgets-container">
{% for widget_settings in widgetsettings.objects.all %}
<div class="widget-content" id="widget-content-{{ widget_settings.pk }}">
not loaded yet
</div>
{% endfor %}
</div>
<script>
// here we use django to render the ajax urls into an object
// in javascript so we can use it on the client side
var ajax_urls = {
{% for widget_settings in widgetsettings.objects.all %}
"{{ widget_settings.pk }}: "{% url ajax_render_data widget_settings.pk %}"{% if not forloop.last %},{% endif %}
{% endfor %}
};
// (I'll assume you're using jQuery)
// start the ajax calls when the page is loaded:
$(document).ready(loadWidgets());
function loadWidgets() {
// loop over the urls we provided from django:
jQuery.each(ajax_urls, function(widget_id, url) {
// do the ajax call:
$.get(url, function(data) {
// put the content into the widget div:
$('#widget-content-'+widget_id).html(data);
});
});
}
</script>
in urls.py:
urlpatterns += patterns('netadmin.plugins.ajax_view',
url(r'^ajax/(?P<object_id>\d+)/$', 'ajax_render_data', name='ajax_render_data'),
)
I am using Django to build a website.
I have a context processor setup that looks something like this:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"mysite.context_processors.mystandardvariables"
)
This adds some standard variables that I like to use in templates, such as SITE_NAME and SITE_ROOT.
I have just created my first custom template tag and I find that I cannot access these standard variables.
I don't get any errors and my page displays ok, it's just that the variable that I want are not available.
To check which variables are available I already used {% debug %}.
My tag looks like this:
#register.inclusion_tag('search/search_snippet.html', takes_context = True)
def search(context):
form = forms.SearchForm()
return {'form': form }
The template for the tag looks like this:
<form action="{{ SITE_ROOT }}search" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
I am including the search tag in my home page like this:
{% extends "base.html" %}
{% load search_tags %}
{% block content %}
{% search %}
{% endblock %}
To answer my own question, I figured out a way to do what I want using a normal template tag rather than an inclusion tag.
#register.tag
def search(parser, token):
return SearchNode()
class SearchNode(template.Node):
def render(self, context):
return render_to_string('search/search_snippet.html',
{ 'form' : forms.FindForm() }, context)
Here I am passing the context through to the function that renders my template to a string.
I would have preferred to implement this as an inclusion tag as it seems like less work, but I wasn't sure how to get it to work.
If anyone knows how to get this working with an inclusion tag please answer and I'll mark your question as the right answer.
I have just started to do a website with django + python and I want to implement a search form to be able to search on all my database objects. What I want is; when I write for an example S I want the search field to display all my objects that starts with the letter S in a list, just like the Tags field below on this site.
Does anyone have a good ide to implement this with django?
For a decent django search implementation, I would recommend looking at djapian. However, for what you are doing, I would recommend a query using the ISTARTSWITH parameter. Consider the following:
views.py
def search(req):
if req.GET:
search_term = req.GET['term']
results = ModelToSearch.objects.filter(field__istartswith=search_term)
return render_to_response('search.html', {'results': results})
return render_to_response('search.html', {})
search.html
<html>
<body>
<form>
<input name='S'>
</form>
{% if results %}
Found the following items:
<ol>
{% for result in results %}
<li>{{result}}</li>
{% endfor %}
</ol>
{% endif %}
</body>
</html>