I'm trying display the outputs of 2 apps on a same web page, but am encountering issues when trying to use the solution proposed here.
I have a "main_app" handling the content of most of the page, and would like to add the output of a "sub_app" (i.e. a rendered <div> element) on the same page.
Here's how I collect the output of sub_app in a main_app view:
from sub_app.views import sub_app_view #
def main_app_view(request):
my_sub_app_html = user_tests(request) #supposed to get rendered HTML content from sub_app
context = {
'sub_app_html ': my_sub_app_html,
}
return render(request, 'main_app.html', context)
Then the view in sub_app:
def sub_app_view(request):
context = {
'sub_app_context': "foo",
}
return render(request, 'sub_app/sub_app.html', context)
main_app.html contains:
<p>
{{ sub_app_html }}
</p>
and sub_app.html:
<div id="mydiv">
{{ sub_app_context }}
</div>
But instead of correctly displaying the rendered HTML from sub_app_view, what is shown in main_app.html in the browser is:
<HttpResponse status_code=200, "text/html; charset=utf-8">.
Is there a solution to this, or a better way to achieve linking between apps?
you can do it using
**
javascript and jquery
**
$.ajax({
type: "get",
url: url_app_1,
data: data,
success: here add your html to your div1,
dataType: dataType
});
$.ajax({
type: "get",
url: url_app_2,
data: data,
success: here add your html to your div2,
dataType: dataType
});
and in the success you can append the html to your div
**
Django solution:
**
The render function return an HttpResponse(content, content_type, status)
so to get the template html you need to:
def main_app_view(request):
my_sub_app_html = user_tests(request)
context = {
# you need to get content then decode
'sub_app_html ': my_sub_app_html.content.decode("utf-8"),
}
return render(request, 'main_app.html', context)
Here is the source code of the render
Related
In my Django web app, I'm trying to dynamically update only a certain section of my page via AJAX, but doing so by returning/replacing HTML in a child template ({% include 'keywords.html' %}). I understand that I can (and maybe should) return a JsonResponse (and I have done so successfully), but I'd like to try and get the below implementation working (as others seem to have).
The view successfully returns the HTML to the AJAX response, but lacking the data contained in the keywords context variable.
templates/index.html
...
<div id="keywords">
{% include 'keywords.html' %}
</div>
...
templates/keywords.html
<div id="keywords">
{% if keywords %}
{% for keyword in keywords %}
<p>{{keyword.word}}</p>
{% endfor %}
{% endif %}
</div>
views.py
def add_keyword(request):
if request.method == 'POST':
form = KeywordForm(request.POST)
if form.is_valid():
...
keywords = Keywords.objects.values()...
print(keywords) # this works, contains a queryset with data
context = {
keywords: keywords,
}
# i've also tried return HttpResponse(render_to_string(...))
# with same result
return render(request, 'keywords.html', context))
index.js
// i've also tried jquery .load()
$.ajax({
url: data.url,
type: "POST",
data:
{
keyword: keyword,
csrfmiddlewaretoken: data.csrf_token
},
success: function(data) {
$("#keywords").html(data);
}
});
AJAX Response data:
<div id="keywords">
</div>
What might I be missing, or doing wrong?
In your context you are missing quotes, when returning the page you have one extra parentheses. It works on my system.
You can render your template with context data using the loade and context
it will do first templates using jinja context will render in html then return final html text then you can pass using JsonResponse
try following stuff then let me know
#view.py
from django.template import context,loader
...
def render_view(request):
if request.method == 'GET':
form = KeywordForm(request.POST)
if form.is_valid():
keywords = Keywords.objects.values()
print(keywords) # this works, contains a queryse
context = {
keywords: keywords,
}
template = loader.get_template('keywords.html')
html = template.render(context)
print(html)
return JsonResponse({'html':html},status=200,content_type="application/json")
#in ajax call success method you should render
success: function(data) {
$("#keywords").html(data);
//or
//ordocument.getElementById('keywords').innerHTML=data;
}
if works or not let me know?
I am trying to fetch data from postgres table by clicking a button in the django template page and the fetched data from db should be populated into another div.
For the same, I am using Ajax get call to fetch the data from DB, but I am facing problem that the value is shown as undefined.
With the Ajax call if I populate the target div with the below, it is working.
$('#childContainer').html(10 + Math.floor(Math.random()*91));
But when I try to fetch the data from table, I am getting undefined.
Here is the code which I have written:-
views.py:-
def index(request):
distinctenvapp = Env_app.objects.values('environment_name').distinct()
return render(request, 'envconfigmgmt/index.html', {'distinctenvapp' : distinctenvapp});
def get(self,request, *args, **kwargs):
if self.request.is_ajax():
return self.ajax(request)
def ajax(self, request):
response_dict= {
'success': True,
}
action = request.GET.get('action','')
if action == 'get_appnames':
env_id = request.GET.get('id','')
if hasattr(self, action):
response_dict = getattr(self, action)(request)
envappname = Env_app.objects.get(environment_name='env_id')
response_dict = {
'application_name':envappname.application_name
}
return HttpResponse(simplejson.dumps(response_dict),
mimetype='application/json')
index.html:-
<div><center><table id="t1"><tr>
{% for obj in distinctenvapp %}
<td>
<button id="{{ obj.environment_name }}">
{{ obj.environment_name }}
</button>
</td>
{% endfor %}
</tr></table></center></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$env_id = $(this).attr('id')
$.ajax({
type: "GET",
data: { action: "get_appnames", id: $env_id },
success: function(data){
$("#childContainer").html("<strong>"+data.application_name+"</strong>");
console.log(data);
}
});
//$('#childContainer').html(10 + Math.floor(Math.random()*91));
});
});
</script>
<div id="childContainer"></div>
I expect the data to be fetched in the target child div.
It should show application names like App1, App2 etc, but it is showing undefined.
IF your ajax request returning JSON content then you have to define datatype in Ajax parameter
$.ajax({
type: "GET",
data: { action: "get_appnames", id: $env_id },
dataType: 'json',
success: function(data){
$("#childContainer").html("<strong>"+data.application_name+"</strong>");
console.log(data);
}
});
For more refere this https://api.jquery.com/jquery.ajax/
I think your ajax request doesnt have url so ajax called current page again
current page is a string and doesnt have application_name
be aware that the mimetype argument was removed in Django 1.7. Use content_type instead.
I would like to have a page in my django application that has a button that search a product and after selecting quantities gets added to the page (without reloading) in a list where the total get calculated (something like that), I am a beginner in programing and I have a week reading and investigated how to do it but I don't found anything.
Is because you need other programming language? Or could you indicate me some documentation or some example that I can read. Mostly because for my inexperience I don't know how to identify the relevant information in the documentation or even what to look for.
This can be done using Ajax call,
check this example:
forms.py
class sampleForm(forms.Form):
input = forms.CharField()
views.py
from django.http import JsonResponse
def sampleview(request):
input = request.POST.get('input', None)
#perform your logic here
#let us say your data is in variable result
result = {'product1' : 'python' ,'product2' : 'django' , 'product3' : 'ajax' }
return JsonResponse(result)
urls.py
from django.urls import path, include
from . import views
urlpatterns = [
path('sampleview',views.sampleview,name='sampleview'),
]
your HTML
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button id="sampleform-submit" type="submit">submit</button>
</form>
<div id="results"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
$("#sampleform-submt").click(function(){
e.preventDefault();
var form = $('#id_input').closest("form")
//id_input is id of input tag generated by form and above line selects the form
$.ajax({
url : "{% url 'sampleview' %}",
type: "POST",
data : form.serialize(),
dataType: 'json',
success: function(data){
#data is 'result' you return in sampleview function
$("#results").append('<p> '+ data.product1 +'</p>');
$("#results").append('<p> '+ data.product2 +'</p>');
$("#results").append('<p> '+ data.product3 +'</p>');
}
});
}
</script>
I hope this helps
I am trying to pass the variable ,I am obtaining from view to the template but it is showing in the preview of the web-browser(chrome) but not on actual screen.
Following is my view file:
analyzer=SentimentIntensityAnalyzer()
data={}
with open('today_5th_oct_new.csv','r',newline='', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
data[row[0]]=float(row[1])
analyzer.lexicon.update(data)
def index(request):
return render(request, "gui/index.html")
#csrf_exempt
def output(request):
sentences = request.POST.get('name',None)
senti = analyzer.polarity_scores(sentences)
context_dict = {'sentiment': senti}
return render(request,"gui/index.html", context = context_dict)
Following is my template-
<!doctype html>
<html>
<head><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script></head>
<body>
<form action>
Enter Sentence:<input id = "name" type = "text" name = "EnterSentence" encoding = "utf-8"><br>
<input onclick = "testfunction()" type = "button" value = "Submit" >
</form>
<div><strong>Score is {{ sentiment }}</strong></div>
</body>
<script>
var testfunction = () => {
var test = document.getElementById("name").value
console.log(test)
$.ajax({
type: "POST",
dataType: "json",
url: 'output/',
data:{
csrfmiddlewaretoken: '{{ csrf_token }}',
'name': test
},
success: function(response) {
console.log("Succesful return firm ajax call");
},
error: function(result){
console.log("Failure");
}
});
}
</script>
I am observing the desired output in preview but not on actual page.
How to resolve that ?
You're getting the response via Ajax but you're not doing anything with it. Your success function needs to insert the content into the page somehow.
To be honest, I don't see why you use Ajax here at all; if you removed the JS code and just let your form do a POST directly it would work fine.
my use case is:
a) Present a form loaded via ajax in a bootstrap modal, the fancy overlay effect stuff.. . I followed these instructions.
This works fine. (see code below)
b) Submit this form back to my Django app, try to validate it, and if it does not validate, re-show the form with the errors in the fancy bootstrap modal.
I can reload the form via ajax, but I m not able to represent it again in the modal.
Note: I did not include the view since it does nothing special. Only instantiating and validating the form.
Quite a lot to read below, so just continue if you think the use case sounds interesting...
My taskList.html looks like this:
<table id="listItemTable" class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<tr>
<td>Task 1</td>
<td><a class="editItem" href="/update/item/1/">edit</a></td>
</tr>
</tbody>
</table>
<div class="modal hide" id="itemFormModal"></div>
<div id="modalExtraJsPlaceholder"></div>
.js for loading the form + showing the bootstrap modal + binding form to a .jquery submit call:
$(document).ready(function() {
modalConnect();
});
<script type="text/javascript">
//connects the modal load for each <a> with class editItem
//Functionality 1
//loads an item edit form from the server and replaces the itemFormModal with the form
//presents the modal with $("#itemFormModal").modal('show');
//Functionality 2
//loads some extra js "modalExtraJsHtml"
//calls the function "submitItemModalFormBind" which has been loaded via "modalExtraJsHtml"
function modalConnect(){
$(".editItem").click(function(ev) { // for each edit item <a>
ev.preventDefault(); // prevent navigation
url = ($(this)[0].href); //get the href from <a>
$.get(url, function(results){
var itemForm = $("#ajax_form_modal_result", results);
var modalExtraJs = $("#modalExtraJs", results);
//get the html content
var modalExtraJsHtml = modalExtraJs.html();
//update the dom with the received results
$('#itemFormModal').html(itemForm);
$('#modalExtraJsPlaceholder').html(modalExtraJsHtml);
$("#itemFormModal").modal('show');
submitItemModalFormBind(); //bind loaded form to ajax call
}, "html");
return false; // prevent the click propagation
})
}
</script>
The itemForm returned from the view looks like this:
<form id="#ajax_form_modal_result" class="well" method="post" action="/update/item/{{ item.id }}">
<div id="ajax_form_modal_result_div">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h3>Edit Item</h3>
</div>
<div class="modal-body">
{% csrf_token %}
{{form.as_p}}
</div>
<div class="modal-footer">
<input class="btn btn-primary" type="submit" value="Save" />
<input name="cancel" class="btn" type="submit" value="Cancel"/>
</div>
</div>
</form>
Loading and showing the modal works fine.
But now comes the second part which does not work as expected. The issue is the following. If the form does not validates, the view returns the form. The returned form should be shown again in the bootstrap modal. But the result is that ONLY the form is presented in the browser, everything else is lost. No css, no table, only the form. Quite ugly.. Thus I did not achieve to update the ajax_form_modal_result_div. Can anyone help me out here what I m doing wrong..!?
The view returns also the js function 'submitItemModalFormBind' which prevents the form default behavior and sends the form via ajax.
<div id="modalExtraJs">
//ajax bind for update item form visualized via modal
function submitItemModalFormBind(){
var url = "{% url updateItem item.pk %}";
$('#ajax_form_modal_result').submit(function(){
$.ajax({
type: "POST",
url: "{% url updateTask item.pk %}",
data: $(this).serialize(),
success:function(response){
var div = $("ajax_form_modal_result_div", response);
$('#ajax_form_modal_result_div').html(div);
},
error: function (request, status, error) {
console.log("failure");
console.log(request.responseText);
}
});
});
return false;
}
</div>
Found a working approach (based upon this solution - and enhanced it with handling of invalid forms) and will post it for anybody who also want to use the stunning beautiful bootstrap modals with django. Major issue with the code above was that I did not correctly disabled the default behavior of the submit button and the approach for loading additional js was not a good idea. So I changed my strategy.
On documentReady or ajaxStop event bind the click event of the hyperlinks to the modalConnect function. Note that you only need the ajaxStop function if you have some kind of ajax which updates the content of your table (which I have):
<script type="text/javascript">
$(document).ready(function() {
modalConnect();
});
</script>
<script type="text/javascript">
$( document ).ajaxStop( function() {
modalConnect();
});
</script>
The modalConnect function which loads the form which we want to present in the modal and a formUpdateURLDiv:
<script type="text/javascript">
function modalConnect()
{
//unbind the click event. If not done we will end up with multiple click event bindings, since binding is done after each ajax call.
$(".editItem").unbind('click');
//bind the click event
$(".editItem").click(function(ev) { // for each edit item <a>
ev.preventDefault(); // prevent navigation
var url = this.href; //get the href from the <a> element
$.get(url, function(results){
//get the form
var itemForm = $("#ajax_form_modal_result", results);
//get the update URL
var formUpdateURLDiv = $("#formUpdateURL", results);
//get the inner html of the div
var formUpdateURL = formUpdateURLDiv.html();
//update the dom with the received form
$('#itemFormModal').html(itemForm);
//show the bootstrap modal
$("#itemFormModal").modal('show');
$(document).ready(function () {
//bind the form to an ajax call. ajax call will be set to the received update url
submitItemModalFormBind(formUpdateURL);
});
}, "html");
return false; // prevent the click propagation
})
}
</script>
the formUpdateURL includes a server generated (see included view below) url to which the loaded form has to make its form submission call. We use this url to "init" the submitItemModalFormBind function:
<script type="text/javascript">
function submitItemModalFormBind(url){
//bind the form. prevent default behavior and submit form via ajax instead
$('#ajax_form_modal_result').submit(function(ev){
$.ajax({
type: "POST",
url: url,
data: $(this).serialize(),
success:function(response, textStatus, jqXHR){
var form = $("#ajax_form_modal_result_div", response);
//form is returned if it is not valid. update modal with returned form
//change this "if" to check for a specific return code which should be set in the view
if (form.html()) {
console.log('Form was invalid and was returned');
//update modal div
$('#ajax_form_modal_result_div').html(form);
$("#itemFormModal").modal('show');
}
//form is not returned if form submission succeeded
else{
//update the entire document with the response received since we received a entire success page and we want to reload the entire page
document.open();
document.write(response);
document.close();
//sort by modified date descending
//var notificationDiv = $("#notification", response);
//$('#notification').html(notificationDiv.html());
console.log('Form was valid and was not returned');
$("#itemFormModal").modal('hide');
}
},
error: function (request, status, error) {
var div = $("ajax_form_modal_result_div", request.responseText);
$('#ajax_form_modal_result_div').html(div);
//implement proper error handling
console.log("failure");
console.log(request.responseText);
}
});
return false;
});
}
</script>
..and to see what is going on at the server see below the view which handles the logic:
class UpdateTaskModalView(LoginRequiredMixin, View):
template = 'list_management/crud/item/update_via_modal.html'
def get_logic(self, request, task_id, **kwargs):
task = get_object_or_404(Task.objects, pk=task_id)
task_form = TaskForm(instance=task)
context = {
'model_form': task_form,
'item': task,
}
return context
def post_logic(self, request, task_id, **kwargs):
task = get_object_or_404(Task.objects, pk=task_id)
task_form = TaskForm(request.POST, instance=task)
if task_form.is_valid():
task = task_form.save(commit=False)
task.modified_by = request.user
task.save()
messages.add_message(request, messages.INFO, 'Item "%s" successfully updated' % (task.name))
return ('redirect', HttpResponseRedirect(reverse('show_list_after_item_update', kwargs={'list_id':task.list.pk, 'item_id':task.pk})))
context = {
'model_form' : task_form,
'list': task.list,
'item': task,
}
return ('context', context)
def get(self, request, task_id, **kwargs):
context = self.get_logic(request, task_id, **kwargs)
return render_to_response(
self.template,
context,
context_instance = RequestContext(request),
)
def post(self, request, task_id, **kwargs):
post_logic_return = self.post_logic(request, task_id, **kwargs)
if post_logic_return[0] == 'redirect':
return post_logic_return[1]
if post_logic_return[0] == 'context':
context = post_logic_return[1]
return render_to_response(
self.template,
context,
context_instance = RequestContext(request),
)
..the form template is already included in my question: ajax_form_modal_result_div, you only have to provide also the formUpdateURL. I did it via the template, which seems quite odd now that I write this post. could be easily provided via the view context.
Voila - Django Forms with Bootstrap Modals! Spice up your UI!
I hope this helps somebody to solve a similar problem.
I wrote this simple AJAX that did the trick for me, hope it helps:
$(document).on('submit', 'div.modal-body form', function(e) {
var form_el = $(this);
e.preventDefault();
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize(),
success: function (xhr, ajaxOptions, thrownError) {
if ( $(xhr).find('.errorlist').length > 0 ) {
form_el.parents('.modal-body').html(xhr);
} else {
form_el.parents('.modal-body').html('<h4>Formulario enviado correctamente</h4>');
}
},
error: function (xhr, ajaxOptions, thrownError) {
form_el.parents('.modal-body').html(xhr);
}
});
});
Oh btw, you will also need something like this in order to load your form into the modal:
$('.modal-class').on('click',function(){
let dataURL = $(this).attr('data-href');
$('.modal-body').load(dataURL,function(){
$('#modal_crear').modal({show:true});
});
});