I am totally new in Django. I am trying to implement datatable server side processing.I have written some codes in my models.py , views.py and urls.py and followed Datatables official documentation also. But unfortunately I am getting error in my terminal and cant able to figure it out how to fix it.
Here is ,
models.py
from django.db import models
class Products(models.Model):
title = models.CharField(max_length=100, blank=True)
description = models.TextField(blank=True)
price = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.title
views.py
from django.shortcuts import render
from ajax_crud.models import Products
from django.http import JsonResponse
def product_json(request):
products_json = Products.objects.all().values('title', 'description', 'price')
data = list(products_json)
value = JsonResponse(data, safe=False)
print(value)
return value
urls.py
from django.urls import path
from ajax_crud.views import product_json
urlpatterns = [
path('json/',product_json,name='json'),
]
demo-datatbles.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<h1>List of Products</h1>
<hr>
<table id="demo-table">
<thead>
<tr>
<th>title</th>
<th>description</th>
<th>price</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function() {
$('#demo-table').DataTable( {
"processing":true,
"serverSide": true,
"ajax": {
"type" : "GET",
"url": "{% url 'json' %}",
"dataSrc": "objects"
},
"columns": [
{ "data": "title" },
{ "data": "description" },
{ "data": "price" },
]
} );
} );
</script>
</body>
</html>
My error in terminal.
[03/Sep/2020 05:31:49] "GET /json/?draw=1&columns%5B0%5D%5Bdata%5D=title&columns%5B0%5D%5Bname%5D=&columns%5B0%5D%5Bsearchable%5D=true&columns%5B0%5D%5Borderable%5D=true&columns%5B0%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B0%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B1%5D%5Bdata%5D=description&columns%5B1%5D%5Bname%5D=&columns%5B1%5D%5Bsearchable%5D=true&columns%5B1%5D%5Borderable%5D=true&columns%5B1%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B1%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B2%5D%5Bdata%5D=price&columns%5B2%5D%5Bname%5D=&columns%5B2%5D%5Bsearchable%5D=true&columns%5B2%5D%5Borderable%5D=true&columns%5B2%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B2%5D%5Bsearch%5D%5Bregex%5D=false&order%5B0%5D%5Bcolumn%5D=0&order%5B0%5D%5Bdir%5D=asc&start=0&length=10&search%5Bvalue%5D=&search%5Bregex%5D=false&_=1599111109862 HTTP/1.1" 200 97
Please someone help me to get rid of it. Help will be highly appreciated.
I recommend working on this in two steps:
Display the basic data (as if you were not using server-side processing).
Add your specific server-side logic.
Background
I will assume your application is processing the HTML template correctly, and building a valid URL in this expression: {% url 'json' %}.
I will also assume that the response being sent to the HTML page from the ajax request is exactly as follows (i.e. the exact JSON data you provided):
[{
"id": 1,
"title": "Neutrogena Oil-Free Acne Wash, 177ML",
"description": "Nice products",
"price": 300
}, {
"id": 2,
"title": "Product one hello2",
"description": "Notes",
"price": 400
}]
If either of these assumptions is false, then the following will probably not help.
(You can use your browser's console to check that the JSON data response is received in the web page. it F12 to open the browser console and inspect the "Network" tab.)
Step 1
We will continue to use "serverSide": true for this step - so, do not remove it.
Your DataTable definition includes the following line:
"dataSrc": "objects"
This means DataTables will look in your JSON for an object using that name. But there is no object named objects - so no data is found.
Therefore you need to remove that line from your template.
But because you are using "serverSide": true, there are more changes needed.
Look at the link I mentioned in my comments (this one). This describes the JSON data you need to pass from the server to DataTables when you respond to the ajax request. There is also an example on the same page (here).
We can therefore take your JSON and make it conform to that requirement:
{
"draw": 1,
"recordsTotal": 1000,
"recordsFiltered": 1000,
"data": [{
"id": 1,
"title": "Neutrogena Oil-Free Acne Wash, 177ML",
"description": "Nice products",
"price": 300
}, {
"id": 2,
"title": "Product one hello2",
"description": "Notes",
"price": 400
}]
}
We have wrapped your data in some additional data, as required for server-side processing. Your data is now in an object named data - which is where DataTables expects to find it, to populate the rows of your table. So, we do not need to use "dataSrc": "data" here - because data is the default (expected) value.
In the above example I used values of 1, 1000 and 1000 - just for testing. You can use these values - and then we will fix them in step 2 below.
So you need to change your Django logic so that it builds the above JSON and returns that to DataTables.
Step 2
Normally (when you do not use server-side processing), the server sends all its data to DataTables at once. DataTables handles all logic for pagination, filtering, and sorting.
But now, with server-side processing, your Django code will be responsible for all of that work. It will not send all the data - it will only one small subset at a time. This is the power of server-side processing: You don't send all 1,000,000 records to the browser (which would crash it). You send only a small, fast subset for each request.
To do this, Django needs to read the request from DataTables. A request is automatically sent by DataTables whenever the user moves to a new page, or performs a sort operation, or filters the data.
Here is one such request - the one you provided in your question:
draw=1
&columns[0][data]=title
&columns[0][name]=
&columns[0][searchable]=true
&columns[0][orderable]=true
&columns[0][search][value]=
&columns[0][search][regex]=false
&columns[1][data]=description
&columns[1][name]=
&columns[1][searchable]=true
&columns[1][orderable]=true
&columns[1][search][value]=
&columns[1][search][regex]=false
&columns[2][data]=price
&columns[2][name]=
&columns[2][searchable]=true
&columns[2][orderable]=true
&columns[2][search][value]=
&columns[2][search][regex]=false
&order[0][column]=0
&order[0][dir]=asc
&start=0
&length=10
&search[value]=
&search[regex]=false
I manually URL-decoded the request, to make it easier to read.
This request contains all the information Django needs in order to build the required response.
For example:
start=0
length=10
This tells you that you need to provide 10 records in the response - and those will be the first 10 records (page 1 has an index of 0).
And this:
order[0][dir]=asc
This tells you that the data needs to be sorted by column 0 (the first column - title) in ascending order.
See here for full details.
So, you need to write all this logic in your Django application - to read the request, and then implement the instructions it contains, to build the correct response.
Related
iam trying to call the nest/node api in crafter cms but it is throwing errors
1)This is my Groovy controller code
import groovy.json.JsonSlurper
def apiUrl = "http://localhost:3000/"
def json = new URL(apiUrl).text //assuming it's json
def object = new JsonSlurper().parseText(json)
templateModel.myObject
2)This is my ftl code
<#import "/templates/system/common/crafter.ftl" as crafter />
<#assign x = contentModel.name_s!"" />
<#crafter.h1>${myObject.x}<#crafter.h1 />
3)after saving the above codes iam getting this error
!(https://i.stack.imgur.com/XQb7f.png)
Is the response at http://localhost:3000/ the following URL JSON?
If not, trying to parse it is going to throw an error.
Also, in your Freemarker template you have an error here:
<#crafter.h1>${myObject.x}<#crafter.h1 />
Since you assigned contentModel.name_s to x, this should simply be:
<#crafter.h1>${x}<#crafter.h1 />
Assuming the response from Node is JSON, and for the sake of the example, let's say it looks like this:
{ mySum: 42, myMessage: "Hello World", theBest: "CrafterCMS" }
Then you can use these values in your freemarker template with:
${myObject.mySum}
myObject is available in the template as myObject because you added it to the template in the controller.
This is my JSON data:
{
"_id": "632833ecf89459939bd47dd5",
"name": "Random Blood Sugar",
"price": 350,
"description": "Random Blood SugarTimely screening can help you in avoiding illnesses and with Healthians Random Blood Sugar you can keep a track of your health in the best way because Healthians is India's leading health test # home service with more than 20 lac satisfied customers across 140+ cities.",
"imgURL": "https://i0.wp.com/post.healthline.com/wp-content/uploads/2021/10/blood-test-sample-tube-1296-728-header.jpg?w=1155&h=1528",
"__v": 0
},
This is my ftl code:
<#import "/templates/system/common/crafter.ftl" as crafter />
<!doctype html>
<html lang="en">
<head>
<#-- Insert your head markup here -->
<#crafter.head />
</head>
<body>
<#crafter.body_top />
<#-- Insert your body markup here -->
<#crafter.h1 $field="demo_s">${myObject.price}</#crafter.h1>
<#crafter.body_bottom />
</body>
</html>
but iam getting the same error. #Russ Danner
I am fairly new to Grails and frameworks in general, so this is most likely a very basic problem. The only promising looking solutions I was able to find were working with the Tag, which is apparently deprecated in Grails 3. Similar questions do exist, but all from the time when was still a thing.
I am trying to program a way of displaying products that are grouped in subcategories which are then grouped in categories. When my page loads the subcategories and categories are requested from my database and selection options (Select-tag and checkboxes) are rendered in the view.
When one of the checkboxes representing the subcategories is checked i need to run a database query to get the product information and update an HTML-element by rendering a template for every row I get back. I have a controller action that does all that. My only problem is that I need a way to call the controller action whenever one of the checkboxes is checked.
I could maybe work around it by using actionSubmit and a hidden submit button that is clicked by javascript whenever a checkbox is checked, but that doesn’t seem like a proper solution.
I am probably missing some very basic functionality here but I did already thoroughly search and haven’t come across a proper solution by now, probably because I didn't use the right search terms. I would be so happy, if anyone could help me with this. Thanks a lot already!
The following example uses a javascript function activated in response to the checkbox being checked/unchecked, the value of which is passed to an action from which you can do whatever with the value of the checkbox, run your query etc. At present the action renders a template to update the view with the database results.
index.gsp
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main" />
<script type="text/javascript">
$(document).ready(function(){
$( '#cb' ).click( function() {
var checked = $(this).is(":checked");
$.ajax( {
url: "/yourController/yourAction?checked=" + checked,
type: "get",
success: function ( data ) {
$( '#resultDiv' ).html( data )
},
error: function(jqXHR, textStatus, errorThrown) {
console.log( 'Error rendering template ' + errorThrown )
}
} );
})
});
</script>
</head>
<body>
<div id="resultDiv"></div>
<g:form>
<g:checkBox name="cb" />
</g:form>
</body>
YourController
class YourController {
def yourAction() {
// you may want to do something with the value of params.checked here?
def dbResults = YourDomain.getStuff()
render ( template: 'theTemp', model: [dbResults: dbResults] )
}
}
_theTemp.gsp
<table>
<caption>Table of stuff</caption>
<g:each in="${dbResults}" var="aThing">
<tr>
<td>${aThing}</td>
</tr>
</g:each>
</table>
How to implement autosuggest using amp-list, amp-mustache, amp-form, and amp-bind?
would like to implement autosuggest for intra-page search
have studied this Google example
would like autosuggest to find US state capitals on a single page in this format
<div id='4'>Little Rock is ...</div>
our JSON structure looks like this
{
"items": [{
"query": "",
"results": [{"Montgomery, Alabama","id='1'"},
{"Juneau, Alaska","id='2'"},
{"Phoenix, Arizona","id='3'"},
{"Little Rock, Arkansas","id='4'"}]
}]
}
have implemented an MCV (minimal, complete, verifiable) example here
how to modify the example to navigate to a specific item on a page based on the selection in results-list?
Here's a quick summary of what you need to do
1. Make a server endpoint that filters results. Make sure it has the appropriate CORS headers.
2. Render the autosuggest items with the ID from the JSON endpoint with a numeric ID
3. Put IDs on each of your or tags.
#2 will look like this
{{#results}}
<div
class='select-option no-outline'
role='option'
tabindex='0'
on='tap:autosuggest-list.hide,{{id}}.scrollTo'
option='{{title}}'
>{{title}}</div>
{{/results}}
Here is the specific build process (Steps A – D)
A. HTML and AMP code:
server endpoint
https://example.com/state_capitals/query
amp-form
<form
method='post'
action-xhr='https://example.com/state_capitals'
target='_blank'
id='search-form'
on='submit:autosuggest-list.hide;submit-success:results.show'
autocomplete='off'
>
HTML input
<div class='search-container'>
<input
id='query'
name='query'
type='text'
class='search-box'
on="input-debounced:AMP.setState({
query: event.value,
autosuggest: event.value
}),
autosuggest-list.show,
results.hide"
[value]="query || ''"
/>
<button class='search-submit' type='submit'>Search</button>
</div>
Above code sets Input Box
amp-list
next, bind results from '/state_capitals/query' endpoint to amp-list and amp-selector components as below:
<amp-list
class='autosuggest-box'
layout='fixed-height'
height='120'
src='/state-capitals/query'
[src]="'/state-capitals/query?q=' + (autosuggest || '')"
id='autosuggest-list'
hidden
>
Source of the amp-list component is from the result of /state-capitals/query in JSON format.
JSON endpoint structure
{"items":[{
"query": "",
"results": [
{"title": "Little Rock, Arkansas", "id":"4"},
{"title": "Olympia, Washington", "id":"47"},
{"title": "Charleston, West Virginia", "id":"48"},
{"title": "Madison, Wisconsin", "id":"49"},
...
]}]}
amp-template
print result of JSON format using amp-mustache component.
<amp-list ...>
<template type='amp-mustache'>
{{#results}}
<amp-selector
keyboard-select-mode='focus'
layout='container'
on='select:AMP.setState({query: event.targetOption}),
autosuggest-list.hide,{{id}}.scrollTo'
>
<div
class='select-option no-outline'
role='option'
tabindex='0'
on='tap:autosuggest-list.hide'
option='{{title}}'
>{{title}}</div>
{{/results}}
</amp-selector>
</template>
</amp-list>
Quick note about amp-selector and on=
The following code:
on='select:AMP.setState({
query: event.targetOption}),
autosuggest-list.hide,{{id}}.scrollTo'
will scroll to:
{{id}}.scrollTo
Where the table row id, for example, is 107
<li>Montgomery</li>
<li>Juneau</li>
<li>Phoenix</li>
<li>Little Rock</li>
B. Endpoint implementation
1. Declare JSON object data as:
Data = [
{"title": "Little Rock, Arkansas", "id":"4"},
...
{"title": "Olympia, Washington", "id":"47"},
{"title": "Charleston, West Virginia", "id":"48"},
{"title": "Madison, Wisconsin", "id":"49"},
];
2. implement a node.js server
app.use('/state_capitals/query', (req, res) => {
assertCors(req, res, ['GET']);
const MAX_RESULTS = 4;
const query = req.query.q;
3. apply node.js script
if (!query) {
res.json({
items: [{
query: "",
results: capitals.slice(0, MAX_RESULTS)
}]
});
} else {
const lowerCaseQuery = query.toLowerCase();
const filtered = capitals.filter(function(e) {return e.title.toLowerCase().includes(lowerCaseQuery)});
res.json({
items: [{
query: "",
results: filtered.slice(0, MAX_RESULTS)
}]
});
}
});
C. NGINX settings
Node.js application runs on domain:< … > and specified port.
Ask Nginx to forward all traffic of port number 80 to a specified port when user runs your website in a browser. This is accomplished using location settings in conf file as
location /state_capitals/ {
proxy_pass http://domain:3002/;
}
D: Implementation
Here is a working version
So I am trying to build myself a blog, and I want a UI for me to update a blog instead messing with the HTML files every time.
I am planning to get the content (blog content containing pics and text) from the quill editor (which is a delta object) then store it into MongoDB.
Then when I need to display it, retrieve it from the DB then render it dynamically using quill-render (https://www.npmjs.com/package/quill-render).
The question is, since I don't know how quill is designed to work so can someone tell me if this is the proper way to do it? Or is it better to let quill somehow export the content to an HTML file, store it then simply redirect to it? Thanks in advance.
I strongly recommend you to store and manipulate the Delta operations. We heavily rely on quill on Wisembly Jam and we manipulate live operations with ShareDB and store them more persistently inside PostgreSQL.
Simply use quill.getContents() to retrieve the ops (this is an array of operations, a simple JSON really easy to store).
Then, when you load your page, retrieve this JSON object from your DB, and use quill.setContents() to load it properly.
This is:
1) smaller to store than HTML
2) future proof (if Quill updates and changes things, it would still properly implement Delta format, not sure it would handle HTML the same way)
The quill documentation recommend's you to manipulate de editor data in the Delta format making it simple to save all your content in Json but, in the other hand you will have to depend on an thirty-party library to render it as HTML.
To use in Delta format, you will have to use setContents() and getContents(). Saving in your DataBase as Delta (See the Snippet in FullScreen for better visualization):
let quillEditor = new Quill('#editor', {
theme: 'snow'
});
quillEditor.on('text-change', function(){
console.clear();
console.log(quillEditor.getContents().ops);
});
//Retrieve your json from MongoDB
let myDocument = [{
"insert": "Hello "
},
{
"attributes": {
"bold": true
},
"insert": "World!"
},
{
"insert": "\n"
}
];
quillEditor.setContents(myDocument, );
<script src="//cdn.quilljs.com/1.3.6/quill.js"></script>
<link rel="stylesheet" href="//cdn.quilljs.com/1.3.6/quill.snow.css">
<div id="editor"></div>
Another approuch that I've used, is to retrieve the HTML directly from the editor with QuillInstance.root.innerHTML, that will allow you to save in your DataBase a direct HTML file, that you can render later:
let quillEditor = new Quill('#editor', {
theme: 'snow'
});
quillEditor.on('text-change', function(){
console.clear();
console.log(quillEditor.root.innerHTML);
});
//Retrieve your json from MongoDB
let myDocument = [{
"insert": "Hello "
},
{
"attributes": {
"bold": true
},
"insert": "World!"
},
{
"insert": "\n"
}
];
quillEditor.setContents(myDocument);
<script src="//cdn.quilljs.com/1.3.6/quill.js"></script>
<link rel="stylesheet" href="//cdn.quilljs.com/1.3.6/quill.snow.css">
<div id="editor"></div>
I have a show which displays a form with fields populated from a document. I'd like to change the values in the field and then save the updated document.
I'm having trouble finding a clear, concise example of how to do this.
Seriously, just finishing this example would work wonders for so many people (I'm going to leave a lot of stuff out to make this concise).
Install Couchapp
This is outside the scope of my question, but here are the instructions for completeness.
Create a couchapp
Again, this is kind outside the scope of my question. Here is a perfectly concise tutorial on how to create a couchapp.
Create a template
Create a folder in the root of your couchapp called templates. Within the templates folder create an HTML page called myname.html. Put the following in it.
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<form method='post' action='#'>
<fieldset>
Hello <input type='text' name='name' value='{{ name }}'>
<input type='submit' name='submit' value='submit'>
</form>
</body>
</html>
Create a show
See the tutorial above for hwo to do this.
Add this code to a show called myname.
function(doc, req) {
if (doc) {
var ddoc = this
var Mustache = require("vendor/couchapp/lib/mustache");
var data = {
title: "The Name",
name: "Bobbert"
}
return Mustache.to_html(ddoc.templates.myname, data)
} else {
return ('nothing here baby')
}
}
Update the document with a new name by ...
So who can complete this step via both the client side and the server side?
Please don't point me to the guide, I need to read it in your words.
Thanks.
Edit:
Although the return value isn't pretty, just posting a form to the update handler will update the document.
You will probably want to look into update handler functions.
An update handler handles granular document transformations. So you can take 1 form, that has one distinct purpose, and only update the relevant fields in your document via the update handler.
Your update handler will need to take a PUT request from your form. A browser can't do this directly, so you'll need some javascript to handle this for you. If you're using jQuery, this plugin can take your form and submit it seamlessly via AJAX using PUT for you.
Inside the function, you can take the fields you are accepting, in this case name and apply that directly to the document. (input validation can be handled via the validate_doc_update function)
Update Handler (in your Design Document)
{
"updates": {
"name": function (doc, req) {
doc.name = req.form.name;
return [doc, "Name has been updated"];
}
}
}
HTML
<form id="myForm" action="/db/_design/ddoc/_update/name/doc_id">...</form>
JavaScript
$(document).ready(function() {
$('#myForm').ajaxForm({
type: "PUT",
success: function () {
alert("Thank you");
}
});
});
Once you've gotten this basic example up and running, it's not much more difficult to add some more advanced features to your update handlers. :)