2013-12-18 3 views
0

Я новичок в Python, MongoDB (mongoengine (ODM)) и каркасе пирамиды в целом. В настоящее время я работаю над проектом с использованием вышеупомянутых технологий, и я хочу использовать jQuery datatables (также новичок в этом). Я нашел ссылку на своем сайте о том, как использовать datatables with MongoDB, но он находится в php, и мои навыки перевода не таковы хорошо.python - jquery datatables with mongodb (mongoengine)

мой вопрос:
Можно ли использовать DataTables с использованием вышеуказанных технологий, если да, то каким образом?

Я попытался преобразовать чужой код, который использовал SQLAlchemy с datatables, но я застрял, поскольку не знаю, как изменить функцию.

@view_config(
route_name='candidate.list.json', 
renderer='json', 
permission="admin" 
) 

def candidate_list_json(context, request): 
    def format_output(vals): 
     vals = list(vals) 
     vals[-1] = """<div class="btn-group"><a href='%s' class=btn>View</a><a href='%s' class=btn>Edit</a></div>""" % (
      request.route_url('candidates', id_number=vals[-1], traverse=()), 
      request.route_url('candidates', id_number=vals[-1], traverse="edit") 
     ) 
     vals[0] = "<a href='%s'>%s</a>" % (request.route_url('candidates', id_number=vals[0], traverse=()), vals[0]) 
     return vals 
    if has_permission('admin', context, request): 
     basefilt = None     # I changed Up to here 
    return handle_datatable(
     request, 
     Agents.id, 
     [Agents.db_agent_id, Agents.db_name, Agents.id_number, Agents.mobile_number, OrgUnits.name, Agents.db_agent_id], 
     lambda term: or_(Agents.db_agent_name.like('%'+term+'%'), OrgUnits.name.like('%'+term+'%'), Agents.mobile_number.like('%'+term+'%'), Agents.id_number.like('%'+term+'%'),), 
     join=[Agents.ou], 
     formatfunc=format_output, 
     base_filt=basefilt 
    ) 

handle_datatable является метод:

def handle_datatable(request, idcol, cols, filtfunc, options=None, cache='short_term', formatfunc=None, displaylength=90, join=None, base_filt=None, outerjoin=None, groupby=None, no_paginate=False, ordercols=None, orderby=None, printquery=False, nocount=False): 
s = sqlahelper.get_session() 
if groupby is not None and type(groupby) != list and type(groupby) != tuple: 
    groupby = [groupby] 

def attachfilt(q, filt, nogroup=False): 
    if filt: 
     q = q.filter(and_(*filt)) 
    if join: 
     q = q.join(*join) 
    if outerjoin: 
     q = q.outerjoin(*outerjoin) 
    if options: 
     q = q.options(*options) 
    if groupby and not nogroup: 
     for g in groupby: 
      q = q.group_by(g) 
    return q 

@cache_region('short_term') 
def perform_count(filt, idcol, term): 
    if not nocount: 
     return attachfilt(s.query(idcol), filt, nogroup=False).count() 
    else: 
     return 0 

#@cache_region('short_term', 'handle_search') 
def perform_search(filt, cols, iStart, iLength, order_cols): 
    q = attachfilt(s.query(*cols), filt) 
    if order_cols: 
     q = q.order_by(*order_cols) 

    if printquery: 
     print q 
    if no_paginate: 
     rows = q.all() 
    else: 
     rows = q[iStart:iStart+iLength] 
    if callable(formatfunc): 
     data = [formatfunc(row[:]) for row in rows] 
    else: 
     data = [row[:] for row in rows] 
    return data 

if not callable(filtfunc): 
    raise Exception("Filter Function is not callable") 
if not cols: 
    raise Exception("Please provide columns to search") 

if not no_paginate: 
    iStart = int(str(request.params.get("iDisplayStart", 0))) 
    iLength = int(str(request.params.get("iDisplayLength", displaylength))) 
else: 
    iStart = 0 
    iLength = 0 

if not ordercols: 
    ordercols = cols 

if orderby: 
    order_cols = orderby 
else: 
    order_cols = [] 
if request.params.get("iSortCol_0", None): 
    iSortingCols = int(str(request.params.get('iSortingCols', 0))) 
    for k in range(0, iSortingCols): 
     iSortCol = int(str(request.params.get('iSortCol_%s' % k, 0))) 
     sSortDir = str(request.params.get('sSortDir_%s' % k, 0)) 
     if str(request.params.get('bSortable_%s' % iSortCol, 'false') == 'true'): 
      col = ordercols[iSortCol] 
      if sSortDir == "asc": 
       order_cols.append(col.asc()) 
      else: 
       order_cols.append(col.desc()) 
search = request.params.get("sSearch", None) 
filt = [] 
if search: 
    filt = filtfunc(search) 
if filt is not None and type(filt) != list: 
    filt = [filt] 
if type(cols) != list: 
    cols = [cols] 


itotal = perform_count([base_filt], idcol, search) 
if no_paginate: 
    iLength = itotal 
if base_filt is not None: 
    filt.append(base_filt) 
cnt = perform_count(filt, idcol, search) 
data = perform_search(filt, cols, iStart, iLength, order_cols) 

return dict(
    sEcho=request.params.get("sEcho", 0), 
    iTotalRecords=itotal, 
    iTotalDisplayRecords=cnt, 
    aaData=data 
) 

Как я уже говорил, я новичок в этих технологий, но я готов учиться, если вы можете просто указать меня в правильном направлении.


UPDATE:

Так что теперь я получил этот код:

import pymongo 
from pyramid_mongo import get_db 

# translation for sorting between datatables api and mongodb 
order_dict = {'asc': 1, 'desc': -1} 


class DataTables_Handler(object): 
    def __init__(self, request, columns, index, collection): 
     self.columns = columns 
     self.index = index 
     self.db = get_db(request) 
     self.collection = collection 

     # values specified by the datatable for filtering, sorting, paging 
     self.request_values = request.params 

     # results from the db 
     self.result_data = None 

     # total in the table after filtering 
     self.cardinality_filtered = 0 

     # total in the table unfiltered 
     self.cadinality = 0 

     self.run_queries() 

    def output_result(self): 
     output = {} 
     output['sEcho'] = str(int(self.request_values['sEcho'])) 
     output['iTotalRecords'] = str(self.cardinality) 
     output['iTotalDisplayRecords'] = str(self.cardinality_filtered) 
     aaData_rows = [] 

     for row in self.result_data: 
      aaData_row = [] 
      for i in range(len(self.columns)): 

       aaData_row.append(row[self.columns[i]].replace('"', '\\"')) 

      # add additional rows here that are not represented in the database 
      # aaData_row.append(('''<input id='%s' type='checkbox'></input>''' % (str(row[ self.index ]))).replace('\\', '')) 

      aaData_rows.append(aaData_row) 

     output['aaData'] = aaData_rows 

     return output 

    def run_queries(self): 

     # pages has 'start' and 'length' attributes 
     pages = self.paging() 

     # the term you entered into the datatable search 
     filters = self.filtering() 

     # the document field you chose to sort 
     sorting = self.sorting() 

     # get result from db 
     self.result_data = self.db.self.collection.find(spec=filters, 
                 skip=pages.start, 
                 limit=pages.length, 
                 sort=sorting) 

     total_count = len(list(self.db.self.collection.find(spec=filters))) 

     self.result_data = list(self.result_data) 

     self.cardinality_filtered = total_count 

     self.cardinality = len(list(self.db.self.collection.find())) 

    def filtering(self): 

     # build your filter spec 
     filters = {} 
     if (self.request_values.has_key('sSearch')) and (self.request_values['sSearch'] != ""): 

      # the term put into search is logically concatenated with 'or' between all columns 
     or_filter_on_all_columns = [] 

      for i in range(len(self.columns)): 
       column_filter = {} 
       column_filter[self.columns[i]] = {'$regex': self.request_values['sSearch'], '$options': 'i'} 
       or_filter_on_all_columns.append(column_filter) 
      filters['$or'] = or_filter_on_all_columns 
     return filters 

    def sorting(self): 
     order = [] 
     # mongo translation for sorting order 

     if (self.request_values['iSortCol_0'] != "") and (self.request_values['iSortingCols'] > 0): 
      order = [] 
      for i in range(int(self.request_values['iSortingCols'])): 
       order.append((self.columns[int(self.request_values['iSortCol_' + str(i)])], order_dict[self.request_values['sSortDir_' + str(i)]])) 
     return order 

    def paging(self): 
     pages = namedtuple('pages', ['start', 'length']) 
     if (self.request_values['iDisplayStart'] != "") and (self.request_values['iDisplayLength'] != -1): 
      pages.start = int(self.request_values['iDisplayStart']) 
      pages.length = int(self.request_values['iDisplayLength']) 
     return pages 

с этим кодом в Вид:

@view_config(
route_name='candidates.list.json', 
renderer='json', 
permission='admin' 
) 
def candidate_list_json(context, request): 
    columns = [ 'id_number', 'first_name', 'email', 'mobile_number'] 
    index_column = "id_number" 
    collection = "candidates" 

    results = DataTables_Handler(request, columns, index_column, collection).output_result() 

    # return the results as a string for the datatable 
    return {"results": results} 

и это в шаблоне:

<a id="btn-addteam" class="btn btn-success" href="{{'add_candidate'|route_url}}"><i class="icon-plus"></i> Add Candidate</a> 
Идентификационный номер Кандидат Имя Кандидат электронной Мобильный телефон Здоровье ->
<script src="{{'kivu:static/datatables/jquery.dataTables.js'|static_url}}"></script> 
    <script src="{{'kivu:static/datatables/dataTables.scroller.js'|static_url}}"></script> 
<script> 
$(document).ready(function() { 
    url = "{{'candidates.list.json'|route_url}}"; 
    var oTable = $('#candidate_search').dataTable({ 
     "bProcessing": true, 
     "bServerSide": true, 
     "sPaginationType": "full_numbers", 
     "bjQueryUI": true, 
     "sAjaxSource": url 
}); 
});</script> 

Но его дает мне ошибку JS:

TypeError: aData is undefined 
    for (var i=0, iLen=aData.length ; i<iLen ; i++) 

мои возвращения ответа GET:

{"results": {"aaData": [], "iTotalRecords": "0", "sEcho": "1", "iTotalDisplayRecords": "0"}} 

В базе данных есть данные. Что мне не хватает? Я надеюсь, что это обновление не в тему ...

+0

Для плагина DataTables для jQuery используйте тег [datatables]. –

+0

Я обновил свой вопрос с правильным тегом ... спасибо – Renier

ответ

1

Конечно, можно использовать jQuery Datatables, используя указанные технологии. Pyramid обрабатывает запросы и управляет подключением к базе данных, обрабатывает запросы в запросах и собирает любые результаты запроса или другие данные в ответ или возвращает данные, которые предоставляются рендерерам, поддерживающим шаблоны, написанные в Chameleon или Mako. Вы добавляете JQuery DataTables к своим шаблонам - это с высоты птичьего полета.

У вас есть по крайней мере 2 способа передачи данных в DataTables

  1. собрать результаты запроса в представлении, возвращающие данные в визуализатор с помощью шаблона хамелеона (http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/quick_tutorial/templating.html), использовать TAL для перебирать данных и сгенерировать действующие DataTables HTML, как показано в DataTables docs.

  2. Если вы закончили с версией 1, переход на AJAX может быть для вас вариантом. Затем вы создаете разметку DataTables в Javascript и используете рендерер JSON для Pyramid, чтобы вернуть ответ JSON на ваш клиент AJAX, скорее всего, используя jQuery. (http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/quick_tutorial/json.html)

Ваш пример смешения слишком много проблем и не из-за сложности. Возьмите любой официальный учебник по пирамиде - вы вряд ли найдете какой-нибудь фрагмент, который трудно читать и понимать. Трудно читать и понимать - по крайней мере, для меня. Кроме того, это никак не проверяется. Пирамидные стартеры должны следовать указанному стилю разработки. Pyramid действительно делает Unit & Функциональное тестирование легко.

Следуйте этому учебник - это стоит время: http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/quick_tutorial/index.html

+0

Спасибо за ваш ответ ... это была полная помощь в пути. У меня есть что-то подобное ... Смотрите обновление. – Renier

+0

понял это правильно ... см. Мой ответ. Я принял вас за ответ, потому что он довел меня до такой степени, что я мог изменить код, который я сделал. Спасибо. – Renier

1

так что я получил его на работу: Я модифицировал этот script:

Я создал модуль под названием инструментов и в __init__.py:

from collections import namedtuple 
import pymongo 


# translation for sorting between datatables api and mongodb 
order_dict = {'asc': 1, 'desc': -1} 


class DataTables_Handler(object): 
    def __init__(self, request, columns, index, collection): 
     self.columns = columns 
     self.index = index 
     #self.db = get_db(request) 
     self.collection = collection 

     # values specified by the datatable for filtering, sorting, paging 
     self.request_values = request.params 

     self.db = pymongo.MongoClient() 

     # results from the db 
     self.result_data = None 

     # total in the table after filtering 
     self.cardinality_filtered = 0 

     # total in the table unfiltered 
     self.cadinality = 0 

     self.run_queries() 

    def output_result(self): 
     output = {} 
     output['sEcho'] = str(int(self.request_values['sEcho'])) 
     output['iTotalRecords'] = str(self.cardinality) 
     output['iTotalDisplayRecords'] = str(self.cardinality_filtered) 
     aaData_rows = [] 
     #print "sEcho", output['sEcho'] 

     for row in self.result_data: 
      print row 
      aaData_row = [] 
      for i in range(len(self.columns)): 

       aaData_row.append(row[self.columns[i]]) 
       #print aData_row 
      #add additional rows here that are not represented in the database 
      aaData_row.append(('''<input id='%s' type='checkbox'></input>''' % (str(row[ self.index ]))).replace('\\', '')) 

      aaData_rows.append(aaData_row) 

     output['aaData'] = aaData_rows 
     print "output: ", output 
     return output 

    def run_queries(self): 
     #call db 
     db = self.db.mydb 

     # pages has 'start' and 'length' attributes 
     pages = self.paging() 

     # the term you entered into the datatable search 
     filters = self.filtering() 

     # the document field you chose to sort 
     sorting = self.sorting() 

     # get result from db 
     self.result_data = db[self.collection].find(spec=filters, 
                skip=pages.start, 
                limit=pages.length, 
                sort=sorting) 

     total_count = len(list(db[self.collection].find(spec=filters))) 

     self.result_data = list(self.result_data) 
     print "result_data", self.result_data 

     self.cardinality_filtered = total_count 

     self.cardinality = len(list(db[self.collection].find())) 
     print "cardinality", self.cardinality 

    def filtering(self): 

     # build your filter spec 
     filters = {} 
     if ('sSearch' in self.request_values.keys()) and (self.request_values['sSearch'] != ""): 

      # the term put into search is logically concatenated with 'or' between all columns 
      or_filter_on_all_columns = [] 

      for i in range(len(self.columns)): 
       column_filter = {} 
       column_filter[self.columns[i]] = {'$regex':  self.request_values['sSearch'], '$options': 'i'} 
      or_filter_on_all_columns.append(column_filter) 
      filters['$or'] = or_filter_on_all_columns 
     return filters 

    def sorting(self): 
     order = [] 
     # mongo translation for sorting order 

     if (self.request_values['iSortCol_0'] != "") and (self.request_values['iSortingCols'] > 0): 
      order = [] 
      for i in range(int(self.request_values['iSortingCols'])): 
       order.append((self.columns[int(self.request_values['iSortCol_' + str(i)])], order_dict[self.request_values['sSortDir_' + str(i)]])) 
     return order 

    def paging(self): 
     pages = namedtuple('pages', ['start', 'length']) 
     if (self.request_values['iDisplayStart'] != "") and (self.request_values['iDisplayLength'] != -1): 
      pages.start = int(self.request_values['iDisplayStart']) 
      pages.length = int(self.request_values['iDisplayLength']) 
     return pages 

и в моем View.py у меня есть:

@view_config(
route_name='candidates.list.json', 
renderer='json', 
permission='admin' 
) 
def candidate_list_json(context, request): 
    columns = [ '_id', 'first_name', 'email', 'mobile_number'] 
    index_column = "_id" 
    collection = "candidates" 

    results = DataTables_Handler(request, columns, index_column, collection).output_result() 
    print "Results: ", results 
    # return the results as a string for the datatable 
    return results 

, а затем в шаблоне у меня есть:

<script src="{{'kivu:static/datatables/jquery.dataTables.js'|static_url}}"></script> 
    <script src="{{'kivu:static/datatables/dataTables.scroller.js'|static_url}}"></script> 
<script> 
    url = "{{'candidates.list.json'|route_url}}"; 
$(document).ready(function() { 
    var oTable = $('#candidate_search').dataTable({ 
     "sScrollY": "425px", 
     // "sPaginationType": "full_numbers", 
     "sAjaxSource": url, 
     "bServerSide": true, 
     "sDom": "<'row'<'col-xs-6 col-md-6 col-lg-6'><'col-xs-6 col-md-6 col-lg-6'f>r>t<'row'<'col-xs-6 col-md-6 col-lg-6'i><'col-xs-6 col-md-6 col-lg-6'>>S", 
     //"sDom": "frtiS", 
     //"sPaginationType": "bootstrap", 
     "bProcessing" : true, 
     // "aoColumnDefs": [{ "bSortable": false, "aTargets": [ 5 ] }], 
     "bDeferRender": true, 
     "bStateSave": true 
    }); 
console.log(oTable); 
     $.extend($.fn.dataTableExt.oStdClasses, { 
      "sSortAsc": "header headerSortDown", 
      "sSortDesc": "header headerSortUp", 
      "sSortable": "header" 
     }); 
     $.extend($.fn.dataTableExt.oStdClasses, { 
      "sWrapper": "dataTables_wrapper form-inline" 
     }); 
    });</script> 

Я надеюсь, что это может помочь кому-то, как и class DataTables_Handler будет использоваться повторно.

Смежные вопросы