I am currently facing a situation can a complicated and I will take the time to explain as clearly as possible my problem.
I use django v1.8
I have a view that shows me a list of results , and the template dedicated to this view, I added ajax method to quickly filter the current results . Everything works fine , but only when the page is refreshed manually the ajax is cleared , I know it's normal, I would I like to do is to change the URL of the browser.
my file.js:
$(function(){
$('#filter').change(function() {
$.ajax({
type: "POST",
url: "/find/object/filter/",
data: {
'preference': $('#preference').val(),
'city': $('#hsearch').val(),
'spec': $('#mplspecialite').val(),
'mplace': $('#mplace').val(),
'filter': $('#filter').val(),
'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
},
success: searchResult,
dataType: 'html'
});
});
});
function searchResult(data, textStatus, jqXHR)
{
$('#dynamic-results').html(data);
}
Ajax view.py:
def ajax_something_search(request):
args = {}
if request.method != "POST":
raise Http404(request.method, _("Not allow method !"))
# code
# code
# code
val_url = urllib.parse.urlencode(args)
url = reverse(
'manage-core:core-search') + '?' + val_url
return HttpResponseRedirect(url)
My search view.py
(I redirect all my ajax param send in this view):
def search_something(request):
args = {}
# code
# code
# code
if request.method == 'GET':
if 'city' in request.GET or 'partner' in request.GET\
or 'filter' in request.GET:
q_city = request.GET.get('city', False)
q_preference = request.GET.get('preference', False)
q_speciality = request.GET.get('speciality', False)
q_partner_name = request.GET.get('partner', False)
q_filter = request.GET.get('filter', False)
args['results'] = args['ctx']
if q_city:
args['results'] = args['results'].filter(
city__name__icontains=q_city)
if q_preference:
args['results'] = args['results'].filter(service=q_preference)
if q_partner_name:
args['results'] = args['results'].filter(
name__icontains=q_partner_name)
if q_filter:
if q_filter == '1':
args['results'] = args['results'].order_by('min_to_order')
elif q_filter == '2':
args['results'] = args['results'].order_by('mark')
elif q_filter == '3':
args['results'] = args['results'].order_by('remarq')
elif q_filter == '4':
args['results'] = args['results'].order_by('name')
if args['results'].count() > 1:
args['filterform'] = SearchFilterForm()
del args['ctx']
template_name = 'something/snippets/'\
'ajax_object_search.html'
return render_to_response(
template_name,
args,
context_instance=RequestContext(request)
)
How can i update the browser url when ajax called ?
The browser URL can be changed programmatically by editing the history entry using history.replaceState
. It's virtually identical to history.pushState
except that pushState
adds a browser history entry and replaceState
modifies the current one. I'll continue with pushState
.
As a word of caution, you will be opening yourself up to more complexity if this is not absolutely needed. This is because you'll have to implement the behaviour to modify the page should somebody navigate backwards in history.
history
is under the DOM window
object.
history.pushState(someState, "some title", "page.html");
someState
is an object that is associated to that browser history entry. e.g. { city: "London", lon: 51.5072, lat: 0.1275 }
The first param (someState
) is subsequently provided when the popstate
event is fired on history change. Another warning, when the browser is reloaded you shouldn't rely on the popstate
event as it may or may not be fired depending on the browser. Grab the state object from history.state
instead as it's there without relying on the event being fired.
The middle param can be the empty string or a string of your choice, it's ignored by browsers for now.
The last param is the URL you want to push into the browser history, it can be absolute or relative. It won't be loaded by the browser.
More Specifically: You could use pushState
in the success callback of your AJAX request which pushes the data sent in the request into a history entry. When the user navigates back or reloads the page, this data can be pulled back and used to send the AJAX request again.
If you anticipate that you'll be doing more of this, you might want to look into in browser routing libraries.
Good luck!
You can read more about HTML5PushState here.
EDIT: Response to the comment.
<!-- language: lang-js -->
$(function(){
$('#filter').change(function() {
var relQuery = null;
// The stuff you send in your request
var reqData = {
'preference': $('#preference').val(),
'city': $('#hsearch').val(),
'spec': $('#mplspecialite').val(),
'mplace': $('#mplace').val(),
'filter': $('#filter').val(),
'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
};
// Make the query string that you need.
// Probably looks like some variant of this.
// Look at jQuery.param docs.
relQuery = "?" + $.param( reqData );
// The request
$.ajax({
type: "POST",
url: "/find/object/filter/",
data: reqData,
success: searchResult,
dataType: 'html'
});
// Change the current history entry to have that
// URL query string.
history.replaceState( {}, '', relQuery);
});
});
function searchResult(data, textStatus, jqXHR) {
$('#dynamic-results').html(data);
}