How do I pass a django model to javascript?
Specifically, I want to pass a django Movie model to javascript.
In javascript, I would like to display the id something in the movie model at the time of score with an if statement.
def index(request):
if Movie.objects.order_by('-stars').exists():
movie = list(Movie.objects.order_by('-stars'))
if TV.objects.order_by('-stars').exists():
tv = TV.objects.order_by('-stars')
print(tv)
context = {
'movie':movie,
}
return render(request, 'Movie/index.html',context)
fetchTrendingResults("all", "week")
var mediaType = document.getElementById("media_type")
mediaType.addEventListener("change", function(event) {
fetchTrendingResults(mediaType.options[mediaType.selectedIndex].value, "day")
})
function fetchTrendingResults(media_type, time_window) {
var trendingDiv = document.getElementById("trendings")
trendingDiv.innerHTML = ""
if (media_type == "score"){
var js_list = {{movie}};
}
else{
fetch(`/api/trendings?media_type=${media_type}&time_window=${time_window}`, {
method: "GET",
headers: {
"Content-Type": "application/json"
}}
// todo:movieとTVのIDをもらってこれをURLにFethして映画とTVの情報をそれぞれでスターが高い順に表示する。
)
.then(res => res.json())
.then(data => {
for (let i=0; i<data.results.length; i++) {
var mainDiv = document.createElement("div");
mainDiv.setAttribute("class", "card");
mainDiv.setAttribute("style", "width: 18rem;");
var img = document.createElement("img");
img.setAttribute("src", "https://image.tmdb.org/t/p/w200" + data.results[i].poster_path);
img.setAttribute("class", "card-img-top");
img.setAttribute("alt", "...");
var body = document.createElement("div");
body.setAttribute("class", "card-body");
var title = document.createElement("h5");
title.setAttribute("class", "card-title");
if (data.results[i].name) {
title.innerHTML = data.results[i].name;
} else {
title.innerHTML = data.results[i].title;
}
//var text = document.createElement("p");
//text.setAttribute("class", "card-text");
//text.innerHTML = data.results[i].overview;
var link = document.createElement("a");
link.setAttribute("href", "/" + data.results[i].media_type + "/" + data.results[i].id + "/");
link.setAttribute("class", "btn btn-primary");
link.innerHTML = "View Details";
body.appendChild(title);
//body.appendChild(text);
body.appendChild(link);
mainDiv.appendChild(img);
mainDiv.appendChild(body);
document.getElementById("trendings").appendChild(mainDiv);
}
})
}
}
How do I pass a django model to javascript?
Specifically, I want to pass a django Movie model to javascript.
In javascript, I would like to display the id something in the movie model at the time of score with an if statement.
You can send model data by just returning JsonResponse from the view (and for example creating JSON dict by forlooping QuerySet, or using model_to_dict Django built-in method) or by preserving your logic and sending html you need to override - even better - you can do both ways at the same time.
So, basically you write view like this:
from django.forms import model_to_dict
from django.http import Http404
def custom_ajax_view(request):
if request.method != 'POST':
raise Http404
movies = Movie.objects.order_by('-stars')
movie_dict = {}
if movies.exists():
movie_dict = {obj.id: model_to_dict(obj) for obj in movies}
tv = TV.objects.order_by('-stars')
tv_dict = {}
if tv.exists():
tv_dict = {obj.id: model_to_dict(obj) for obj in tv}
context = {
'movie': movie,
}
html = render_to_string(
'Movie/index.html', context=context)
return JsonResponse({
'movies': movie_dict,
'tvs': tv_dict,
'html': html,
})
And then you retrieve data via Ajax method (I prefer using jQuery for that) by writing:
$.ajax({
url: CUSTOM_AJAX_URL,
type: 'post',
dataType: 'json',
success: function (data) {
// Here you retrieve your data and you can do something with it.
console.log(data)
}
});
You also can resolve your CUSTOM_AJAX_URL using template logic (post it at the end of template)
<script>
const CUSTOM_AJAX_URL = "{% url 'custom_ajax_view' %}";
</script>
<script src="{% static 'your_script_name.js' %}"></script>
Then your script should see the CUSTOM_AJAX_URL (if you use script not directly by using inline method, but including script via script tag and placing it with static method in the code). If you place it directly, you can pass URL directly to the AJAX method.
Related
I am implementing ajax in my list views page. Now I am facing problems for rendering image. How to get my image src link of each object ?
views.py:
class PostJsonListView(View):
def get(self, *args, **kwargs):
print(kwargs)
upper = kwargs.get('num_posts')
lower = upper - 1
posts = list(Blog.objects.values('id','title','body','blog_header_image')[lower:upper])
posts_size = len(Blog.objects.filter(is_published='published'))
max_size = True if upper >= posts_size else False
return JsonResponse({'data':posts,'max': max_size},safe=False)
.html
<div class="card mb-4" id="card mb-4"></div>
<script>
const postsBox = document.getElementById('card mb-4')
console.log(postsBox)
const spinnerBox = document.getElementById('spinner-box')
const loadBtn = document.getElementById('load-btn')
const loadBox = document.getElementById('loading-box')
let visible = 1
const handleGetData = () => {
$.ajax({
type: 'GET',
url: `/posts-json/${visible}/`,
success: function(response){
maxSize = response.max
const data = response.data
spinnerBox.classList.remove('not-visible')
setTimeout(()=>{
spinnerBox.classList.add('not-visible')
data.map(post=>{
console.log(post.id)
postsBox.innerHTML += `<img class="img-fluid rounded" style="max-height:1000px;max-width:1200px;" src="" alt="..." />`
})
if(maxSize){
console.log('done')
loadBox.innerHTML = "<h4>No more posts to load</h4>"
}
}, 500)
},
error: function(error){
console.log(error)
}
})
}
handleGetData()
loadBtn.addEventListener('click', ()=>{
visible += 3
handleGetData()
})
</script>
How to get object href so user can click an view the details page? also how to render image url?
When getting image url by using values() in django you will not get the path of your image to get path you need to prepend your MEDIA_URL for each object like this:
from django.conf import settings
posts = list(Blog.objects.values('id','title','body','blog_header_image')[lower:upper])
for post in posts:
post['blog_header_image'] = settings.MEDIA_URL + post['blog_header_image']
and then in your javascript you can access the image like this:
postsBox.innerHTML += "<img ... src="+post.blog_header_image+"</>"
Or you could do it like this:
posts = list(Blog.objects.all()[lower:upper])
data = list()
for post in posts:
data.append({'id': post.id, 'title': post.title, 'image_url': post.blog_header_image.url})
return JsonResponse({'data':data,'max': max_size},safe=False)
And then in javascript:
postsBox.innerHTML += "<img ... src="+post.image_url+"</>"
I'm trying to make an ajax call (I specifically don't want to do it using ActionLink).
I'm having a controller that is like this:
public IActionResult ExportUsers(List<string> listOfEmails)
{
/*some data processing*/
return File(result, "text/csv", "ExportCandidates.csv");
}
On the other side with ajax I do this simple call:
$.ajax({
url: '/Admin/Testcenter/GenerateInvitationPreview',
type: 'post',
data: {
//some input data to send to the controller
},
success: function (response) {
)
}
});
I know there exists something for pdf files where you return a base64 file and with the response in the ajax call you just write something like pdfWindow.document.write(...) and this will open a new window with a pdf file.
Is there a way to extract the response for my CSV file and generate it so the user downloads it ?
USE NPOI Library for Excel Sheet Generation
//Generate Excel Sheet
try
{
Guid gid = Guid.NewGuid();
string ext = ".xls";
string[] Headers = { "Appointments Id", "Date of Appointment", "Doctor Name", "Patient Name", "Visit Type", "Status" };
string fileName = "AppointmentsExcelSheet_" + gid.ToString() + ext;
var serverpath = _env.ContentRootPath;
string rootpath = serverpath + "/wwwroot/ExcelSheets/" + fileName;
FileInfo file = new FileInfo(Path.Combine(rootpath, fileName));
var memorystream = new MemoryStream();
using (var fs = new FileStream(rootpath, FileMode.Create, FileAccess.Write))
{
IWorkbook workbook = new XSSFWorkbook();
ISheet excelSheet = workbook.CreateSheet("Appointments List");
IRow row = excelSheet.CreateRow(0);
var font = workbook.CreateFont();
font.FontHeightInPoints = 11;
font.FontName = "Calibri";
font.Boldweight = (short)FontBoldWeight.Bold;
for (var i = 0; i < Headers.Length; i++)
{
var cell = row.CreateCell(i);
cell.SetCellValue(Headers[i]);
cell.CellStyle = workbook.CreateCellStyle();
cell.CellStyle.SetFont(font);
}
var result = _Appointment.GetAppoinmentsPDf();
int index = 1;
foreach (var app in result.Items)
{
//var PatientDob = Convert.ToDouble(app.PatientDOB);
row = excelSheet.CreateRow(index);
row.CreateCell(0).SetCellValue(app.AppointmentId);
row.CreateCell(1).SetCellValue(app.DateofAppointment+" "+app.TimeofAppointment);
row.CreateCell(2).SetCellValue(app.DoctorFullName);
row.CreateCell(3).SetCellValue(app.SelectedPatientName);
row.CreateCell(4).SetCellValue(app.PurposeofVisit);
if (app.IsActive == false)
{
row.CreateCell(5).SetCellValue("Inactive");
}
else
{
row.CreateCell(5).SetCellValue("Active");
}
index++;
}
workbook.Write(fs);
}
using (var filestream = new FileStream(rootpath, FileMode.Open))
{
filestream.CopyToAsync(memorystream);
}
memorystream.Position = 0;
//send filepath to JQuery function
response.Msg = "/ExcelSheets/" + fileName;
}
catch (Exception Ex)
{
//exception code
}
return Ok(reponse.Msg)
//JavaScript
function AppointmentsExcelSheet() {
//var token = Token;
//var link = path;
debugger
$.ajax({
//'Content-Type': 'application/pdf.',
type: "GET",
url: "/api/Appointments/GetAppointmentsExcelSheet",
beforeSend: function () {
$.blockUI({
message: ('<img src="/images/FadingLines.gif"/>'),
css: {
backgroundColor: 'none',
border: '0',
'z-index': 'auto'
}
});
},
complete: function () {
$.unblockUI();
},
success: function (data) {
debugger
//downloads your Excel sheet
window.location.href = data.msg;
}
});
}
The best way to do what you want to do is to not use AJAX, but use either a link click that opens a new window (since you are passing in parameters) If you could use a
<form target="_blank">
to open a form response. Inside the form can be a field or fields that contains the list of emails (it can be one field, or multiple input fields with the same name). Your action handler can accept that list, parse it, and return a File response, and the natural result of opening the new window from the form post operation is a file that opens up.
I am creating a notification center, naturally it must be visible throughout the site; So the question is how do I do it.
Create a name.js file inside the static folder but it seems that something is missing since apart from the delay in the app itself it is not visible outside it.
view.py
#csrf_exempt
def NewsSubjects(request):
if request.is_ajax() == True:
queryset = Downloads.objects.all().order_by('register_date').values()[:5]
data=list(queryset)
return JsonResponse(data, safe=False)
urls.py
path('alerts/', views.NewsSubjects, name='alerts'),
/static/js/notifications.js
$.ajax({
// initialize an AJAX request
url: "alerts",
// al estar en static no se usa el name del URL ('control:alert') sino el PATH (alerts/)
type: "GET",
datatype:'json',
success: function(data) {
console.log('cambio')
var opciones = document.getElementById("nuevasDisciplinas");
var countAlert = document.getElementById("countAlert");
var listaDisciplinas = ''
for (var i = 0; i < data.length; i++) {
// console.log(data[i]);
var nombDis = data[i].category_name
var fechaCreacion = data[i].register_date
// var d = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(fechaCreacion)
// var m = new Intl.DateTimeFormat('en', { month: 'short' }).format(fechaCreacion)
// var a = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(fechaCreacion)
var icon = '<divclass="mr-3"><divclass="icon-circle bg-primary"><iclass="fas fa-file-alt text-white"></i></div></div>'
var body ='<div><divclass="small text-gray-500">'+fechaCreacion+'</div><spanclass="font-weight-bold">'+nombDis+'</span></div>'
listaDisciplinas += icon+body
}
opciones.innerHTML = listaDisciplinas;
countAlert.innerHTML = data.length;
},
error: function() {
console.log("The information could not be obtained");
}
});
master.html
<script src="{% static 'js/notifications.js' %}"></script>
the idea is simple, bring the latest records according to the date of registration (the best option would be the login date to the system but good), this works in the notification app but not in the rest.
It returns the message that I put in case of error.
PS: if you can lend me a hand with the formatting of the date it would be fine too
you have to use the path of the url instead of the name, that is, the name of the app/url/
Django the urls.py they consist of path(this_url, view, name_url) so to use it throughout the Django site you must use app/this_url/
in my case
my urls.py
path('alerts/', views.NewsSubjects, name='alerts'),
in the ajax url it would be
$.ajax({
url: "app_name/alerts/",
...
});
I'm trying to send ajax post requests to my server to add or remove objects by using just checkboxes (not form). Here is a screenshot of what I got visually:
https://pasteboard.co/IMHHSa6.png
When I click any of the checkboxes I got http500 (internal server error) as response. In cmd I see the error that says there is no matching query: app1.models.Influencer.DoesNotExist: Influencer matching query does not exist.
The thing is I'm pretty sure that the object with that id exists in the database. I spend much time inspecting Django's CSRF documentation and watching youtube videos about django-ajax examples. Here is my code:
views.py:
class InfluencerListView(LoginRequiredMixin, ListView):
model = Influencer
context_object_name = 'influencers' # not necessary, default is object_list
def post(self, request, *args, **kwargs):
inf_id = request.POST.get('inf.id')
list_id = request.POST.get('list.id')
i = Influencer.objects.get(id=inf_id)
l = InfluencerList.objects.get(id=list_id)
l.influencers.add(i)
data = {
'result' : 'some result'
}
return JsonResponse(data)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
logged_in_user = self.request.user
context['myLists'] = logged_in_user.lists.annotate(influencers_count=Count('influencers'))
return context
models.py:
class Influencer(models.Model):
# fields are not included for the sake of clarity
class InfluencerList(models.Model):
name = models.CharField('Name:', max_length=20, blank=False)
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='lists')
influencers = models.ManyToManyField('Influencer', related_name='lists')
scripts.js
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function myFunc(_self) {
inf_id = _self.getAttribute('data-inf_id');
list_id = _self.getAttribute('data-list_id');
console.log(inf_id + " " + list_id); # I CAN SEE THOSE IDS IN CONSOLE AND THEY EXIST IN DB
var csrftoken = getCookie('csrftoken');
if(_self.checked == true){
console.log("checked!");
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$.ajax({
method: 'POST',
url: '/influencers',
data: {
'inf_id': inf_id,
'list_id': list_id,
'csrfmiddlewaretoken': csrftoken
},
dataType: 'json',
success: function (data) {
console.log("succes!");
}
});
}
else{
console.log("unchecked!");
}
}
I also added this line somewhere in my view file (where I put it doesn't matter as long as it's in the body since I'm not using any forms. Please correct me if I'm wrong):
<input type='hidden' name='csrfmiddlewaretoken' value='{{ csrf_token }}' />
I have an django app in which I am trying to store the gridster widget configuration in the form of JSON variable to database.But when I click"Update" button on my webpage my database does not stores any value.
My JS Code which sends serial value to database
var gridster;
var $color_picker = $('#color_picker');
var URL = "{% url 'save-grid' %}";
gridster = $(".gridster ul").gridster({
widget_base_dimensions: [80, 80],
widget_margins: [5, 5],
helper: 'clone',
resize: {
enabled: true
}
}).data('gridster');
$(".add-button").on("click", function() {
$('#test').click();
$('#test').on('change', function(e) {
var test = document.getElementById('test');
if (!test) {
alert("Um, couldn't find the fileinput element.");
}
else if (!test.files) {
alert("This browser doesn't seem to support the `files` property of file inputs.");
}
else if (!test.files[0]) {
alert("Please select a file before clicking 'Load'");
}
else {
file = test.files[0];
console.log(file);
fr = new FileReader();
fr.readAsDataURL(file);
fr.onload = function() {
var data = fr.result; // data <-- in this var you have the file data in Base64 format
callbackAddButton(data);
test.value = '';
$('#test').replaceWith($('#test').clone())
};
}
})
});
function callbackAddButton(file) {
// get selected color value
var color = $color_picker.val();
// build the widget, including a class for the selected color value
var $widget = $('<li>', {
'class': 'color_' + color
})
.append($('<button>', {
'class': 'delete-button',
'text':'-'
}))
.append($(`<img src="${file}" height="60px" width="60px">`));
// add widget to the grid
gridster.add_widget($widget, 1, 1);
}
$('.js-seralize-update').on('click', function () {
var s = gridster.serialize();
updated_grid=JSON.stringify(s);
$('#log').val(updated_grid);
function updategridster(){
var data = updated_grid;
$.post(URL, data, function(response){
if(response === 'success'){ alert('Yay!'); }
else{ alert('Error! :('); }
});
}
});
$('.gridster').on("click", ".delete-button", function() {
gridster.remove_widget($(this).parent());
});
var serialization = updated_grid
serialization = Gridster.sort_by_row_and_col_asc(serialization);
$('.js-seralize-restore').on('click', function () {
gridster.remove_all_widgets();
$.each(serialization, function () {
gridster.add_widget('<li />', this.size_x, this.size_y, this.col, this.row);
});
});
My urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'myapp/save-grid$', views.save_grid, name='save-grid'),
]
My views.py
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.shortcuts import render, redirect
from django.utils import timezone
from django.utils.encoding import smart_str
from django.http import HttpResponse
from os import path
from .models import update_grid
def save_grid(request):
if request.method == 'POST':
data = json.loads(request.body)
grid = update_grid(data=data)
grid.save()
return HttpResponse('success') # if everything is OK
My Models.py
from django.db import models
from django.utils import timezone
from jsonfield import JSONField
class update_grid(models.Model):
title = models.CharField(max_length=255, blank=True)
data = JSONField()
def __str__(self):
return self.title
I am able to add JSON variable through admin.But nof able to get where I am making mistake
I am just not sure about my javascript part.Whether I have written passing of variable to django syntactically correct
Fiddle
Edit 1
My JS Script is updated as follows
var URL = "{% url 'save-grid' %}";
$('.js-seralize-update').on('click', function () {
var s = gridster.serialize();
updated_grid=JSON.stringify(s);
$('#log').val(updated_grid);
function updategridster(updated_grid){
var data = updated_grid;
$.post(URL, data, function(response){
if(response === 'success'){ alert('Yay!'); }
else{ alert('Error! :('); }
});
}
updategridster(updated_grid);
});
Now I get this error
POST http://localhost:8000/calendar_grid/save-grid net::ERR_CONNECTION_ABORTED jquery.min.js:2
I think the problem is how you are reading the data in Django since request.body returns a byte string
Try replacing this javascript line
var data = updated_grid;
with
var data = {json: updated_grid}
Then in your django view access it via request.POST like this
def save_grid(request):
if request.method == 'POST':
json_data = request.POST.get('json')
print(json_data) # Can add a print here for testing
data = json.loads(json_data)
grid = update_grid.objects.create(data=data, title='title')
return HttpResponse('success') # if everything is OK
Also if you have errors with the csrf_token this is helpful https://docs.djangoproject.com/en/2.0/ref/csrf/#ajax