2012-05-24 26 views
7

Trước tiên, tôi đã đọc câu hỏi "jQuery Grid Recommendations" nhưng nó không trả lời cho câu hỏi của tôi.Đề xuất Lưới jQuery có thể chỉnh sửa với REST API

Tôi có một nhỏ REST API with MongoDB Backend chỉ:

Nhận tất cả equipements:

GET /equipements HTTP/1.1 
{{_id:key1, name:Test Document 1, plateforme:prod}, {_id:key2, name:Test Document 2, plateforme:prod}, ...} 

Nhận equipement với phím: key1

GET /equipements/key1 HTTP/1.1 
{"_id": "key1", "name": "Test Document 1", "plateforme": "prod"} 

Thêm equipement mới

PUT /equipements HTTP/1.1 {"_id": "key8", "name": "Test Document 3", "plateforme": "prod"} 
HTTP/1.0 200 OK 

Bây giờ, tôi cần tìm một cách dễ dàng để cho phép người dùng lambda thêm/xem/del thiết bị. Vì vậy, tôi nghĩ rằng một giao diện web với một jQuery như UI là tốt nhất. Tôi tried với Sencha Rest Proxy nhưng tôi không biết javascript và tôi không thể điều chỉnh ví dụ.

Cách sửa javascript của tôi cho chương trình phụ trợ REST của tôi?

VÀ/HOẶC

bạn có thể giới thiệu một giải pháp đơn giản để Sencha Nghỉ ngơi Proxy? (mà làm việc với REST backend của tôi)

Trả lời: jqGrid

VÀ/HOẶC

gì jQuery Lưới bạn muốn giới thiệu cho tôi? (mà làm việc với REST backend của tôi)

Trả lời: jqGrid

cuối cùng câu hỏi: Tại sao tế bào của tôi là không thể chỉnh sửa với nhấn đúp chuột?

Phụ lục

Server Side (EDIT: Thêm tole 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> 
+0

"Tôi không biết javascript" - Điều đó sẽ phải thay đổi nếu bạn đang cố gắng tạo giao diện người dùng REST. Dành thời gian để học JavaScript; nó sẽ kết thúc và nó không phải là một ngôn ngữ rất khó. – RustyTheBoyRobot

+0

Chỉ dành cho nhóm nội bộ và không phải là công việc của tôi để viết lối vào web. Một ngày, tôi sẽ học javascript. Nhưng bây giờ, tôi có nhiều thứ quan trọng hơn. – Yohann

Trả lời

7

Bạn có thể sử dụng jqGrid để giao tiếp với dịch vụ RESTfull của bạn. jqGrid hỗ trợ chế độ chỉnh sửa cây: chỉnh sửa ô, chỉnh sửa nội tuyến và chỉnh sửa biểu mẫu. Hơn nữa, việc chỉnh sửa nội tuyến có thể được khởi tạo theo nhiều cách khác nhau. Ví dụ, người ta có thể gọi phương thức editRow bên trong số onSelectRow hoặc ondblClickRow gọi lại hoặc sử dụng navGrid để thêm nút "Xóa" trong thanh công cụ navigatorinlineNav để thêm nút "Thêm" và "Chỉnh sửa". Một cách khác sẽ là sử dụng formatter: "actions" để bao gồm các nút "chỉnh sửa" trong một cột của lưới. Bạn có thể tìm tất cả các cách trong the official jqGrid demo. Chi tiết triển khai kỹ thuật khác bạn có thể tìm thấy trong the answer.

Tôi thấy cá nhân quan trọng là bạn hiểu một khía cạnh quan trọng khác của việc sử dụng các dịch vụ RESTfull trong giao diện web. Vấn đề là API RESTfull tiêu chuẩn không có bất kỳ giao diện chuẩn nào để phân loại, phân trang và lọc dữ liệu. Tôi cố gắng giải thích vấn đề dưới đây. Sau đó tôi hy vọng nó sẽ rõ ràng khuyến nghị của tôi để mở rộng API RESTfull chuẩn hiện tại với các phương thức bổ sung có tham số bổ sung và cung cấp chức năng sắp xếp, phân trang và lọc.

Vấn đề rất dễ hiểu nếu bạn có tập dữ liệu lớn. Nó không có ý nghĩa để hiển thị trong lưới ví dụ 10000 hàng dữ liệu cùng một lúc. Người dùng không thể xem dữ liệu trên màn hình mà không cần scolling hoặc phân trang dữ liệu. Hơn nữa, vì cùng một lý do, nên thực hiện sắp xếp và thậm chí lọc dữ liệu. Vì vậy, thực tế hơn là chỉ hiển thị một trang dữ liệu ngay từ đầu và cung cấp cho người dùng một số giao diện để phân trang dữ liệu. Trong các tiêu chuẩn pager của jqGrid trông giống như

enter image description here

người dùng có thể đi đến "Next", "Last", "trước" hay "đầu tiên" trang hoặc chọn kích thước trang:

enter image description here

thêm người dùng có thể chỉ định các trang mong muốn bằng cách nhập trực tiếp của các trang mới và cấp bách của Nhập:

enter image description here

Trong cùng một cách người dùng có thể nhấp vào tiêu đề của bất kỳ cột để sắp xếp dữ liệu lưới bởi các cột:

enter image description here

Một yếu tố giao diện người dùng rất quan trọng (quan trọng từ những người sử dụng điểm xem) có thể là một số giao diện lọc như here ví dụ hoặc giao diện tìm kiếm như here.

Tôi cung cấp cho bạn ví dụ từ jqGrid, nhưng tôi thấy vấn đề là phổ biến. Tôi muốn nhấn mạnh rằng dịch vụ RESTfull cung cấp cho bạn không có giao diện chuẩn để sắp xếp, phân trang và lọc dữ liệu.

Trong trường hợp sử dụng jqGrid địa chỉ REST mặc định sẽ nhận được theo mặc định thông số bổ sung. Đó là: page, rows chỉ định số trang và kích thước trang sẽ được yêu cầu từ dịch vụ, các thông số sidxsord chỉ định cột sắp xếp và hướng sắp xếp và _searchfilters (mục cuối cùng là the format). lọc. Người ta có thể đổi tên các tham số nếu cần sử dụng tùy chọn prmNames của jqGrid.

Tôi khuyên bạn nên đọc the answer về câu hỏi được hỏi về mã hóa URL. Tôi nghĩ rằng phần _search=false&rows=20&page=1&sidx=&sord=asc không thuộc về tài nguyên và vì vậy tốt hơn nên gửi thông tin như thông số chứ không phải là một phần của URL.

Điều tôi chủ yếu muốn thể hiện trong câu trả lời của tôi là việc sử dụng API RESTfull cổ điển thuần túy không đủ để triển khai giao diện người dùng tốt. Bạn sẽ phải mở rộng giao diện với các tham số bổ sung được sử dụng để phân trang, sắp xếp và lọc hoặc bạn sẽ không thể tạo giao diện web thân thiện với người dùng và người dùng.

+0

Cảm ơn câu trả lời dài này. Bit nó không trả lời cho câu hỏi của tôi: Trong thực tế, nó không thể sử dụng jQGrid với phần phụ trợ REST của tôi. jQGrid sử dụng định dạng jsojn cụ thể: '{total: xxx, page: yyy, hồ sơ: zzz, hàng: [ {name1:” Row01 ″, name2: ”Hàng 11 ″, name3:” Hàng 12 ″, name4: ”Row 13 ″, name5: ”Hàng 14 ″}, ...' – Yohann

+0

@Yohann: Không! jqGrid có thể đọc hầu hết định dạng JSON * bất kỳ, bạn chỉ nên sử dụng [jsonReader] tương ứng (http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data). Bạn không mô tả định dạng dữ liệu hiện tại của bạn chi tiết, nhưng tôi cho rằng sau đây 'jsonReader' sẽ làm việc trong trường hợp của bạn:' jsonReader: {repeatitems: false, id: "_id", root: function (obj) {return obj; }, bản ghi: hàm (obj) {return obj.length; }, page: function (obj) {return 1; }, total: function (obj) {return 1; }} ' – Oleg

+0

@Yohann: Định dạng chuẩn của dữ liệu đầu vào trông hơi lạ, nhưng nếu bạn gửi từ mảng máy chủ của chuỗi thay vì * tên * thuộc tính, bạn có thể giảm kích thước dữ liệu được truyền giữa máy chủ và máy khách. Hơn nữa nó yêu cầu người dùng chỉ định * duy nhất * 'id' của mỗi hàng vì id này sẽ được sử dụng như' id' của '' - rowid. – Oleg

Các vấn đề liên quan