mirror of
https://github.com/frappe/books.git
synced 2024-12-22 19:09:01 +00:00
get_all with filters
This commit is contained in:
parent
2ed02ea846
commit
80699c833a
118
README.md
118
README.md
@ -2,22 +2,124 @@
|
||||
|
||||
Core libs for Frappe Framework JS
|
||||
|
||||
### Examples
|
||||
## Examples
|
||||
|
||||
### Declaring Models
|
||||
|
||||
Models are declared by adding a `.json` model file in the `models/doctype` folder of the module/app.
|
||||
|
||||
{
|
||||
"autoname": "hash",
|
||||
"name": "ToDo",
|
||||
"doctype": "DocType",
|
||||
"issingle": 0,
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "subject",
|
||||
"label": "Subject",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"label": "Description",
|
||||
"fieldtype": "Text"
|
||||
},
|
||||
{
|
||||
"fieldname": "status",
|
||||
"label": "Status",
|
||||
"fieldtype": "Select",
|
||||
"options": [
|
||||
"Open",
|
||||
"Closed"
|
||||
],
|
||||
"default": "Open",
|
||||
"reqd": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
### Setup / Migrate
|
||||
|
||||
const frappe = require('frappe-core);
|
||||
|
||||
# init database
|
||||
frappe.init();
|
||||
|
||||
# make a new todo
|
||||
// sync all schema from `models` folders in all apps
|
||||
frappe.migrate();
|
||||
|
||||
### Managing Documents
|
||||
|
||||
Frappe Object-Relational-Mapper (ORM) helps you manage (create, read, update, delete) documents based on the DocTypes declared
|
||||
|
||||
#### Create
|
||||
|
||||
const frappe = require('frappe-core);
|
||||
frappe.init();
|
||||
|
||||
// make a new todo
|
||||
let todo = frappe.get_doc({doctype: 'ToDo', subject: 'something'})
|
||||
todo.insert()
|
||||
|
||||
# get all todos
|
||||
let total_open = 0;
|
||||
for (let d of frappe.get_all('ToDo')) {
|
||||
todo = frappe.get_doc('ToDo', d.name);
|
||||
if (todo.status == 'Open') total_open += 1;
|
||||
#### Read
|
||||
|
||||
const frappe = require('frappe-core);
|
||||
frappe.init();
|
||||
|
||||
// get all open todos
|
||||
let todos = frappe.db.get_all('ToDo', ['name'], {status: "Open"});
|
||||
let first_todo = frappe.get_doc('ToDo', toods.name);
|
||||
|
||||
|
||||
#### Update
|
||||
|
||||
const frappe = require('frappe-core);
|
||||
frappe.init();
|
||||
|
||||
// get all open todos
|
||||
let todos = frappe.db.get_all('ToDo', ['name'], {status: "Open"});
|
||||
let first_todo = frappe.get_doc('ToDo', toods.name);
|
||||
|
||||
first_todo.status = 'Closed';
|
||||
first_todo.update();
|
||||
|
||||
### Metadata
|
||||
|
||||
const frappe = require('frappe-core);
|
||||
|
||||
frappe.init();
|
||||
|
||||
let todo_meta = frappe.get_meta('ToDo');
|
||||
|
||||
// get all fields of type "Data"
|
||||
let data_fields = todo_meta.fields.map(d => d.fieldtype=='Data' ? d : null);
|
||||
|
||||
### Controllers
|
||||
|
||||
You can write event handlers in controllers, by declaring a `.js` file in the `models/doctype/` folder along with the model file.
|
||||
|
||||
The name of the class must be the slugged name of the DocType
|
||||
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
class todo extends frappe.document.Document {
|
||||
validate() {
|
||||
// set default status as "Open" if not set
|
||||
if (!this.status) {
|
||||
this.status = 'Open';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { todo: todo };
|
||||
|
||||
### Database
|
||||
|
||||
You can also directly write SQL with `frappe.db.sql`
|
||||
|
||||
const frappe = require('frappe-core);
|
||||
|
||||
frappe.init();
|
||||
|
||||
all_todos = frappe.db.sql('select name from todo');
|
||||
|
||||
|
@ -43,20 +43,21 @@ class Database {
|
||||
}
|
||||
}
|
||||
|
||||
migrate() {
|
||||
for (let doctype in frappe.models.path_map.doctype) {
|
||||
if (this.table_exists(doctype)) {
|
||||
this.alter_table(doctype);
|
||||
} else {
|
||||
this.create_table(doctype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create_table(doctype) {
|
||||
let meta = frappe.get_meta(doctype);
|
||||
let columns = [];
|
||||
|
||||
// add standard fields
|
||||
let fields = frappe.model.standard_fields.slice();
|
||||
if (meta.istable) {
|
||||
fields = fields.concat(model.child_fields);
|
||||
}
|
||||
|
||||
// add model fields
|
||||
fields = fields.concat(meta.fields);
|
||||
|
||||
for (let df of fields) {
|
||||
for (let df of this.get_fields(meta)) {
|
||||
if (frappe.model.type_map[df.fieldtype]) {
|
||||
columns.push(`${df.fieldname} ${frappe.model.type_map[df.fieldtype]} ${df.reqd ? "not null" : ""} ${df.default ? ("default " + frappe.utils.sqlescape(df.default)) : ""}`);
|
||||
}
|
||||
@ -68,6 +69,13 @@ class Database {
|
||||
return this.sql(query);
|
||||
}
|
||||
|
||||
alter_table(doctype) {
|
||||
// add columns
|
||||
|
||||
// change columns
|
||||
|
||||
}
|
||||
|
||||
get(doctype, name) {
|
||||
let doc = frappe.db.sql(`select * from ${frappe.slug(doctype)} where name = ${frappe.db.escape(name)}`);
|
||||
return doc ? doc[0] : {};
|
||||
@ -88,6 +96,29 @@ class Database {
|
||||
set ${assigns.join(", ")}`);
|
||||
}
|
||||
|
||||
get_all(doctype, fields=['name'], filters, start, limit) {
|
||||
return this.sql(`select ${fields.join(", ")}
|
||||
from ${frappe.slug(doctype)}
|
||||
${filters ? "where" : ""} ${this.get_filter_conditions(filters)}
|
||||
${limit ? ("limit " + limit) : ""} ${start ? ("offset " + start) : ""}`);
|
||||
}
|
||||
|
||||
get_filter_conditions(filters) {
|
||||
// {"status": "Open"} => `status = "Open"`
|
||||
// {"status": "Open", "name": ["like", "apple%"]}
|
||||
// => `status="Open" and name like "apple%"
|
||||
let conditions = [];
|
||||
for (let key in filters) {
|
||||
const value = filters[key];
|
||||
if (value instanceof Array) {
|
||||
conditions.push(`${key} ${value[0]} ${this.escape(value)}`);
|
||||
} else {
|
||||
conditions.push(`${key} = ${this.escape(value)}`);
|
||||
}
|
||||
}
|
||||
return conditions.join(" and ");
|
||||
}
|
||||
|
||||
sql(query, opts={}) {
|
||||
//console.log(query);
|
||||
const result = frappe.db._conn.exec(query);
|
||||
@ -109,6 +140,23 @@ class Database {
|
||||
escape(value) {
|
||||
return frappe.utils.sqlescape(value);
|
||||
}
|
||||
|
||||
get_fields(meta) {
|
||||
// add standard fields
|
||||
let fields = frappe.model.standard_fields.slice();
|
||||
if (meta.istable) {
|
||||
fields = fields.concat(frappe.model.child_fields);
|
||||
}
|
||||
|
||||
// add model fields
|
||||
fields = fields.concat(meta.fields);
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
table_exists(table) {
|
||||
return this.sql(`SELECT name FROM sqlite_master WHERE type='table' AND name='${table}'`) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
function sql_result_to_obj(result) {
|
||||
|
@ -4,7 +4,7 @@ const frappe = require('frappe-core');
|
||||
describe('Controller', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
frappe.db.create_table('ToDo');
|
||||
frappe.db.migrate();
|
||||
});
|
||||
|
||||
it('should call controller method', () => {
|
||||
|
@ -4,10 +4,43 @@ const frappe = require('frappe-core');
|
||||
describe('Document', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
frappe.db.migrate();
|
||||
});
|
||||
|
||||
// it('should create a table', () => {
|
||||
// frappe.db.create_table('ToDo');
|
||||
// frappe.db.write();
|
||||
// });
|
||||
it('should insert and get values', () => {
|
||||
frappe.db.sql('delete from todo');
|
||||
frappe.get_doc({doctype:'ToDo', subject: 'testing 1'}).insert();
|
||||
frappe.get_doc({doctype:'ToDo', subject: 'testing 3'}).insert();
|
||||
frappe.get_doc({doctype:'ToDo', subject: 'testing 2'}).insert();
|
||||
|
||||
let subjects = frappe.db.get_all('ToDo', ['name', 'subject']).map(d => d.subject);
|
||||
|
||||
assert.ok(subjects.includes('testing 1'));
|
||||
assert.ok(subjects.includes('testing 2'));
|
||||
assert.ok(subjects.includes('testing 3'));
|
||||
});
|
||||
|
||||
it('should filter correct values', () => {
|
||||
let subjects = null;
|
||||
|
||||
frappe.db.sql('delete from todo');
|
||||
frappe.get_doc({doctype:'ToDo', subject: 'testing 1', status: 'Open'}).insert();
|
||||
frappe.get_doc({doctype:'ToDo', subject: 'testing 3', status: 'Open'}).insert();
|
||||
frappe.get_doc({doctype:'ToDo', subject: 'testing 2', status: 'Closed'}).insert();
|
||||
|
||||
subjects = frappe.db.get_all('ToDo', ['name', 'subject'],
|
||||
{status: 'Open'}).map(d => d.subject);
|
||||
|
||||
assert.ok(subjects.includes('testing 1'));
|
||||
assert.ok(subjects.includes('testing 3'));
|
||||
assert.equal(subjects.includes('testing 2'), false);
|
||||
|
||||
subjects = frappe.db.get_all('ToDo', ['name', 'subject'],
|
||||
{status: 'Closed'}).map(d => d.subject);
|
||||
|
||||
assert.equal(subjects.includes('testing 1'), false);
|
||||
assert.equal(subjects.includes('testing 3'), false);
|
||||
assert.ok(subjects.includes('testing 2'));
|
||||
|
||||
});
|
||||
});
|
@ -4,7 +4,7 @@ const frappe = require('frappe-core');
|
||||
describe('Document', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
frappe.db.create_table('ToDo');
|
||||
frappe.db.migrate();
|
||||
});
|
||||
|
||||
it('should insert a doc', () => {
|
||||
|
@ -4,6 +4,7 @@ const frappe = require('frappe-core');
|
||||
describe('Meta', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
frappe.db.migrate();
|
||||
});
|
||||
|
||||
it('should get init from json file', () => {
|
||||
|
@ -4,6 +4,7 @@ const frappe = require('frappe-core');
|
||||
describe('Models', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
frappe.db.migrate();
|
||||
});
|
||||
|
||||
it('should get todo json', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user