2016-03-15 72 views
0

我正在使用Flask-Eve爲我的數據提供一個API。我想用Eve來插入我的記錄,這樣我就可以得到一個_created屬性和其他Eve添加的屬性。如何在Flask Eve中插入有記錄和列表的記錄?

我的兩個字段是字典,一個是列表。當我試圖將它插入伊娃時,結構似乎變得平坦,失去了一些信息。試圖告訴夏娃字典&列表元素給我一個POST錯誤,說這些字段需要是字典和列表,但他們已經是!請有人可以幫我&告訴我我做錯了什麼?

我夏娃的conf是這樣的:

'myendpoint': { 'allow_unknown': True, 
        'schema': { 'JobTitle': { 'type':  'string', 
              'required':  True, 
              'empty':   False, 
              'minlength':   3, 
              'maxlength':  99 }, 
           'JobDescription': { 'type': 'string', 
                'required':  True, 
                'empty':   False, 
                'minlength':  32, 
                'maxlength':  102400 }, 
          }, 
       }, 

但是當我發佈以下結構使用要求:

{ 
     "_id" : ObjectId("56e840686dbf9a5fe069220e"), 
     "Salary" : { 
       "OtherPay" : "On Application" 
     }, 
     "ContactPhone" : "xx", 
     "JobTypeCodeList" : [ 
       "Public Sector", 
       "Other" 
     ], 
     "CompanyName" : "Scc", 
     "url" : "xx", 
     "JobTitle" : "xxx", 
     "WebAdID" : "TA7494725_1_1", 
     "JobDescription" : "xxxx", 
     "JobLocation" : { 
       "DisplayCity" : "BRIDGWATER", 
       "City" : "BRIDGWATER", 
       "StateProvince" : "Somerset", 
       "Country" : "UK", 
       "PostalCode" : "TA6" 
     }, 
     "CustomField1" : "Permanent", 
     "CustomField3" : "FTJOBUKNCSG", 
     "WebAdManagerEmail" : "xxxx", 
     "JobType" : "Full", 
     "ProductID" : "JCPRI0UK" 
} 

的交行看起來是這樣的:

resp = requests.post(url, data = job) 

它得到'變平'並丟失信息從列表和列表:

{ 
     "_id" : ObjectId("56e83f5a6dbf9a6395ea559d"), 
     "Salary" : "OtherPay", 
     "_updated" : ISODate("2016-03-15T16:59:06Z"), 
     "ContactPhone" : "xx", 
     "JobTypeCodeList" : "Public Sector", 
     "CompanyName" : "Scc", 
     "url" : "xxx", 
     "JobTitle" : "xx", 
     "WebAdID" : "TA7494725_1_1", 
     "JobDescription" : "xxx", 
     "JobLocation" : "DisplayCity", 
     "CustomField1" : "Permanent", 
     "_created" : ISODate("2016-03-15T16:59:06Z"), 
     "CustomField3" : "FTJOBUKNCSG", 
     "_etag" : "55d8d394141652f5dc2892a900aa450403a63d10", 
     "JobType" : "Full", 
     "ProductID" : "JCPRI0UK" 
} 

我試着更新我的模式說有的字典和列表:

 'JobTypeCodeList': { 'type': 'list'}, 
    'Salary':   { 'type': 'dict'}, 
    'JobLocation':  { 'type': 'dict'}, 

但後來當我在新的記錄文章中,我得到一個錯誤說

{u'Salary': u'must be of dict type', u'JobTypeCodeList': u'must be of list type', u'JobLocation': u'must be of dict type'}, 

我已經在POST之前驗證過type(job.Salary) == dict等,所以我不知道如何解決這個問題。雖然我可以將記錄直接發佈到MongoDB中,但繞過夏娃,如果可能的話,我寧願使用夏娃。

回答

0

如果這對其他人有用,我最終通過在Eve中發佈一個扁平結構來解決此問題,然後使用on_insert和on_update事件循環鍵並從中構造對象(和列表) 。

這有點複雜,但它訣竅,現在它已經到位,它使用相當透明。我對象通過夏娃加入到MongoDB中現在有嵌入列表和散列,但他們也得到了方便前夕屬性,如_created和_updated,而POST和PATCH請求也打不通夏娃的正常模式進行驗證。

唯一真正尷尬的是on_insert和on_update發送稍有不同的參數,所以在下面的代碼中有很多重複,我還沒有重構。

任何字符可被用作標誌:我使用兩個下劃線以指示哪些應該結束了作爲一個單一的對象鍵/值和兩個&字符爲值應分成的列表。現在我張貼的結構是這樣的:

"Salary__OtherPay" : "On Application" 
    "ContactPhone" : "xx", 
    "JobTypeCodeList" : "Public Sector&&Other", 
    "CompanyName" : "Scc", 
    "url" : "xx", 
    "JobTitle" : "xxx", 
    "WebAdID" : "TA7494725_1_1", 
    "JobDescription" : "xxxx", 
    "JobLocation__DisplayCity" : "BRIDGWATER", 
    "JobLocation__City" : "BRIDGWATER", 
    "JobLocation__StateProvince" : "Somerset", 
    "JobLocation__Country" : "UK", 
    "JobLocation__PostalCode" : "TA6" 
    "CustomField1" : "Permanent", 
    "CustomField3" : "FTJOBUKNCSG", 
    "WebAdManagerEmail" : "xxxx", 
    "JobType" : "Full", 
    "ProductID" : "JCPRI0UK" 

我的夏娃架構已相應更新,以驗證這些新的鍵名的值。然後在後臺,我定義低於該檢查輸入的鍵/值,並將其轉換爲對象/列表,並刪除原__和& &數據的功能:

import re 

def flat_to_complex(items=None, orig=None): 

    if type(items) is dict: # inserts of new objects 
     if True: # just to force indentation 
      objects = {} # hash-based container for each object 
      lists = {} # hash-based container for each list 

      for key,value in items.items(): 
       has_object_wildcard = re.search(r'^([^_]+)__', key, re.IGNORECASE) 
       if bool(has_object_wildcard): 
        objects[has_object_wildcard.group(1)] = None 
       elif bool(re.search(r'&&', unicode(value))): 
        lists[key] = str(value).split('&&') 

      for list_name, this_list in lists.items(): 
       items[list_name] = this_list 

      for obj_name in objects: 

       this_obj = {} 
       for key,value in items.items(): 
        if key.startswith('{s}__'.format(s=obj_name)): 
         match = re.search(r'__(.+)$', key) 
         this_obj[match.group(1)] = value 
         del(items[key]) 

       objects[obj_name] = this_obj 

      for obj_name, this_obj in objects.items(): 
       items[obj_name] = this_obj 

    elif type(items) is list: # updates to existing objects 
     for idx in range(len(items)): 
      if type(items[idx]) is dict: 
       objects = {} # hash-based container for each object 
       lists = {} # hash-based container for each list 

       for key,value in items[idx].items(): 
        has_object_wildcard = re.search(r'^([^_]+)__', key, re.IGNORECASE) 
        if bool(has_object_wildcard): 
         objects[has_object_wildcard.group(1)] = None 
        elif bool(re.search(r'&&', unicode(value))): 
         lists[key] = str(value).split('&&') 

       for list_name, this_list in lists.items(): 
        items[idx][list_name] = this_list 

       for obj_name in objects: 

        this_obj = {} 
        for key,value in items[idx].items(): 
         if key.startswith('{s}__'.format(s=obj_name)): 
          match = re.search(r'__(.+)$', key) 
          this_obj[match.group(1)] = value 
          del(items[idx][key]) 

        objects[obj_name] = this_obj 

       for obj_name, this_obj in objects.items(): 
        items[idx][obj_name] = this_obj 

然後我就告訴夏娃運行在插入和更新,其功能是該集合:

app.on_insert_myendpoint += flat_to_complex 
app.on_update_myendpoint += flat_to_complex 

這實現了我所需要的,並在蒙戈所產生的記錄是一樣的,從上面的問題的一個(與_created和_updated屬性)。這顯然不是理想的,但它到達那裏,一旦到位就很容易。