带有 REST API 的可编辑 jQuery Grid 推荐
首先,我已经阅读了问题 例如或像 这里.
我给你一个来自 jqGrid 的例子,但我发现这个问题很常见.我想强调的是,RESTfull 服务没有为您提供对数据进行排序、分页和过滤的标准接口.
在使用 jqGrid 的情况下,RESTfull url 将默认获取 附加 参数.它是:page
、rows
指定将从服务中询问的页码和页面大小、sidx
和 sord
指定排序列和排序方向的参数以及 _search
和 filters
(最后在 格式) 允许支持过滤.如果需要,可以使用 jqGrid 的 prmNames 选项重命名参数.
我建议您阅读关于 URL 编码问题的答案.我认为 _search=false&rows=20&page=1&sidx=&sord=asc
部分不属于资源,因此最好将信息作为 parameters 而不是作为 URL 的一部分.
我在回答中主要想表达的是,纯经典 RESTfull API 的使用不足以实现良好的用户界面.您必须使用用于分页、排序和过滤的附加参数来扩展界面,否则您将无法创建高性能和用户友好的 Web GUI.
First, i already read the question "jQuery Grid Recommendations" but it doesn't answer to my question.
I have a small REST API with MongoDB Backend just :
Get all equipements :
GET /equipements HTTP/1.1
{{_id:key1, name:Test Document 1, plateforme:prod}, {_id:key2, name:Test Document 2, plateforme:prod}, ...}
Get equipement with the key : key1
GET /equipements/key1 HTTP/1.1
{"_id": "key1", "name": "Test Document 1", "plateforme": "prod"}
Add new equipement
PUT /equipements HTTP/1.1 {"_id": "key8", "name": "Test Document 3", "plateforme": "prod"}
HTTP/1.0 200 OK
Now, I need to find an easy way to allow lambda user to add/view/del equipments. So i think a web interface with a jQuery like UI is the best. I tried with Sencha Rest Proxy but I do not know javascript and I fails to adapt the example.
How fix my javascript for my REST backend?
AND/OR
Can you recommend a simpler alternative to Sencha Rest Proxy? (which works with my REST backend)
Answer : jqGrid
AND/OR
What jQuery Grid would you recommend me? (which works with my REST backend)
Answer : jqGrid
Final question : Why my cells are not editable with double click ?
Appendices
Server Side (EDIT : Add methode POST)
#!/usr/bin/python
import json
import bottle
from bottle import static_file, route, run, request, abort, response
import simplejson
import pymongo
from pymongo import Connection
import datetime
class MongoEncoder(simplejson.JSONEncoder):
def default(self, obj):
# convert all iterables to lists
if hasattr(obj, '__iter__'):
return list(obj)
# convert cursors to lists
elif isinstance(obj, pymongo.cursor.Cursor):
return list(obj)
# convert ObjectId to string
elif isinstance(obj, pymongo.objectid.ObjectId):
return unicode(obj)
# dereference DBRef
elif isinstance(obj, pymongo.dbref.DBRef):
return db.dereference(obj)
# convert dates to strings
elif isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date) or isinstance(obj, datetime.time):
return unicode(obj)
return simplejson.JSONEncoder.default(self, obj)
connection = Connection('localhost', 27017)
db = connection.mydatabase
@route('/static/<filename:path>')
def send_static(filename):
return static_file(filename, root='/home/igs/restlite/static')
@route('/')
def send_static():
return static_file('index.html',root='/home/igs/restlite/static/')
@route('/equipements', method='PUT')
def put_equipement():
data = request.body.readline()
if not data:
abort(400, 'No data received')
entity = json.loads(data)
if not entity.has_key('_id'):
abort(400,'No _id specified')
try:
db['equipements'].save(entity)
except ValidationError as ve:
abort(400, str(ve))
@route('/equipements', method='POST')
def post_equipement():
data = request.forms
if not data:
abort(400, 'No data received')
entity = {}
for k,v in data.items():
entity[k]=v
if not entity.has_key('_id'):
abort(400,'No _id specified')
try:
db['equipements'].save(entity)
except ValidationError as ve:
abort(400, str(ve))
@route('/equipements/:id', methodd='GET')
def get_equipement(id):
entity = db['equipements'].find_one({'_id':id})
if not entity:
abort(404, 'No equipement with id %s' % id)
return entity
@route('/equipements', methodd='GET')
def get_equipements():
entity = db['equipements'].find({})
if not entity:
abort(404, 'No equipement')
response.content_type = 'application/json'
entries = [entry for entry in entity]
return MongoEncoder().encode(entries)
run(host='0.0.0.0', port=80)
EDIT : JQGrid :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Rest Proxy Example</title>
<link rel="stylesheet" type="text/css" href="/static/css/ui.jqgrid.css" />
<link rel="stylesheet" type="text/css" href="/static/css/jquery-ui-1.8.20.custom.css" />
<script type="text/javascript" src="/static/js/jquery.js"></script>
<script type="text/javascript" src="/static/js/jquery.jqGrid.min.js"></script>
<script type="text/javascript" src="/static/js/grid.locale-fr.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
var lastsel;
jQuery("#list2").jqGrid({
url:'equipements',
datatype: "json",
colNames:['Id','Name', 'Plateforme'],
colModel:[
{name:'_id',index:'_id', width:50, editable:true},
{name:'name',index:'_id', width:300, editable:true},
{name:'plateforme',index:'total', width:200,align:"right", editable:true},
],
rowNum:30,
rowList:[10,20,30],
pager:'pager2',
sortname: '_id',
viewrecords: true,
width: 600,
height: "100%",
sortorder: "desc",
onSelectRow: function(_id){
if(_id && _id!==lastsel){
jQuery('#liste2').jqGrid('restoreRow',lastsel);
jQuery('#liste2').jqGrid('editRow',_id,true);
lastsel=_id;
}
},
jsonReader: {
repeatitems: false,
id: "_id",
root: function (obj) { return obj; },
records: function (obj) { return obj.length; },
page: function (obj) { return 1; },
total: function (obj) { return 1; }
},
editurl:'equipements',
caption:"Equipements"
});
jQuery("#list2").jqGrid('navGrid','#pager2',{edit:true,add:true,del:true});
});
</script>
</head>
<body>
<table id="list2"></table>
<div id="pager2"></div>
<br />
</body>
</html>
解决方案
You can use jqGrid to communicate with your RESTfull service. jqGrid supports tree editing modes: cell editing, inline editing and form editing. Moreover the inline editing can be initialized in different ways. For example one can call editRow method inside of onSelectRow
or ondblClickRow
callback or use navGrid to add "Delete" button in the navigator toolbar and inlineNav to add "Add" and "Edit" buttons. Another way will be to use formatter: "actions" to include "editing" buttons in one column of the grid. You can find all the ways in the official jqGrid demo. More technical implementation details you can find in the answer.
I find personally important that you understand another important aspect of the usage of RESTfull services in the web front-end. The problem is that standard RESTfull API don't any standard interface for sorting, paging and filtering of the data. I try to explain the problem below. After that I hope it will be clear my recommendation to extend the current standard RESTfull API with additional methods which have additional parameters and which provide sorting, paging and filtering functionality.
The problem is very easy to understand if you have large dataset. It has no sense to display in the grid for example 10000 rows of data at once. The user is unable to see the data on the screen without scolling or paging of data. Moreover because of the same reasons it has sense to implement sorting and even filtering of the data. So it is much more practical to display only one page of data at the beginning and give the user some interface for paging the data. In the standard pager of jqGrid which looks like
the user can go to the "Next", "Last", "Previous" or "First" page or choose the page size:
additionally the user can specify the desired page by direct input of the new page and pressing of Enter:
In the same way the user can click on the header of any column to sort the grid data by the column:
Another very important user interface element (important from the users point of view) could be some filtering interface like here for example or searching interface like here.
I give you example from jqGrid, but I find the problem as common. I want to emphasize that RESTfull service gives you no standard interface for sorting, paging and filtering of the data.
In case of usage jqGrid the RESTfull url will get by default additional parameters. It's: page
, rows
which specify the page number and the page size which will be asked from the service, sidx
and sord
parameters which specify the sorting column and the sorting direction and _search
and filters
(the last is in the format) which allows to support filtering. One can rename the parameters if needed using prmNames option of jqGrid.
I recommend you to read the answer on the question which are asked about the encoding of the URL. I think that the part _search=false&rows=20&page=1&sidx=&sord=asc
is not belong to resource and so it's better to send the information as parameters and not as the part of URL.
What I mainly wanted to express in my answer is that the usage of pure classical RESTfull API is not sufficient to implement good user interface. You will have to extend the interface with additional parameters used for paging, sorting and filtering or you will be not able to create performant and user friendly web GUI.
相关文章