2013-07-29 33 views
3

我正在試驗stdnet,我對這個應該是一個相對簡單的案例有挑戰。redis/stdnet數據模型追蹤

如果我填充我的模型(見下文<hr>),不指定主鍵的值,我得到:

stdnet.utils.exceptions.FieldValueError: {"author_id": "Field 'author_id' is required for 'main.book'."}

author1 = models[Author](name='Jeff Doyle') 

然而,對於id增加值使代碼工作..

author1 = models[Author](name='Jeff Doyle', id=1) 

Author.idodm.AutoIdField()。由於這是一個分層數據模型,因此我可能能夠理解手動將id = odm.AutoIdField()添加到我的模型的要求。但是,文檔說明odm.AutoIdField會自動生成主鍵的值。

我的問題:爲什麼我需要手動指定一個值爲id當我填充我的模型?

我跑stdnet 0.8.2瓦特/用Cython,關於Python 2.6.6和Debian 6.0(內核2.6.32-5-AMD64)。


工作實例:

from stdnet import odm 

class Author(odm.StdModel): 
    id = odm.AutoIdField(primary_key=True, unique=True) 
    name = odm.SymbolField() 

    def __unicode__(self): 
     return self.name 

class Book(odm.StdModel): 
    id = odm.AutoIdField(primary_key=True, unique=True) 
    title = odm.CharField() 
    author = odm.ForeignKey(Author, related_name='books') 

    def __unicode__(self): 
     return "<Book '%s' by %s>" % (self.title, self.author) 

if __name__=='__main__': 
    models = odm.Router('redis://localhost:6379?db=0') 
    models.register(Author) 
    models.register(Book) 

    session = models.session() 
    session.begin() 
    author1 = models[Author](name='Jeff Doyle', id=1) 
    session.add(author1) 
    book1 = models[Book](title='Routing TCP/IP, Volume 1', id=2, author=author1) 
    session.add(book1) 
    session.commit() 

回溯:

Traceback (most recent call last): 
    File "stdnet_example.py", line 31, in <module> 
    session.commit() 
... 
stdnet.utils.exceptions.FieldValueError: {"author_id": "Field 'author_id' is required for '__main__.book'."} 
+0

因爲你來了一個「要求」字段 –

+0

我也試過沒有'required',但我仍然得到traceback –

回答

3

我相信問題是,你試圖插入這本書和作者在同一會話。所以在提交時,作者還沒有被保存到數據庫中,因此沒有該圖書在外鍵中引用的id。

我認爲它應該工作,如果你在嘗試添加書之前提交作者。事情是這樣的:

session.begin() 
author1 = models[Author](name='Jeff Doyle') 
session.add(author1) 
session.commit() 

session.begin() 
book1 = models[Book](title='Routing TCP/IP, Volume 1', author=author1) 
session.add(book1) 
session.commit() 

我看到有由有類似的問題,以你這樣的人在GitHub上提出的問題,並沒有從stdnet的作者a response in the comments。我認爲他基本上和我說的是一樣的東西,但你可以自己閱讀。

0

首先,我不知道庫(其實我一直在尋找這一點,那謝謝啦 :) )。我認爲models.register不僅會在您的程序中註冊模型,還會在Redis服務器上註冊。所以你要麼必須清除數據庫,要麼可以找到改變模型的方法。

希望它可以幫助

0

我使用不同於James Holderness推薦的語法結束了;他的回答很有幫助,但我在原始問題中使用的語法對於複雜的odm.ForeignKey模型似乎不起作用。我最終轉換到了不同的語法,這是我在這裏記錄的,因爲python-stdnet 0.8文檔有點混亂。

構建DB:

if __name__=='__main__': 
    ## assuming we have a test redis db at localhost:6379 
    models = odm.Router('redis://localhost:6379?db=0') 
    models.register(Publisher) 
    models.register(Author) 
    models.register(Book) 
    session = models.session() 

    session.begin() # Start a redis session 
    authors = list() 
    for author in ['Leo Tolstoy', 'unknown ghostwriter']: 
     authors.append(models.author.new(name=author)) 
    publisher = models.publisher.new(name='Penguin Books') 
    session.commit() 

    for title in ['Anna Karenina', 'War and Peace']: 
     print "Writing", title 
     book = models.book.new(name=title, publisher=publisher) 
     for author in authors: 
      book.authors.push_back(author) # push_back() appends to odm.ListField 
    session.commit() # Write to the redis db 

查詢DB:

## assuming we have a test redis db at localhost:6379 
    models = odm.Router('redis://localhost:6379?db=0') 
    models.register(Publisher) 
    models.register(Author) 
    models.register(Book) 
    session = models.session() 

    qs = models.book.filter(name__contains='War and Peace') # search Book.name 
    print "You found", list(qs) 

模型定義(既用於構建和查詢):

import sys 

from stdnet import odm 

class Publisher(odm.StdModel): 
    name = odm.SymbolField() 

    def __unicode__(self): 
     return self.name 

class Author(odm.StdModel): 
    name = odm.SymbolField() 

    def __unicode__(self): 
     return self.name 

class Book(odm.StdModel): 
    name = odm.CharField() 
    authors = odm.ListField(model=Author) 
    publisher = odm.ForeignKey(Publisher, related_name='publishers') 


    def __unicode__(self): 
     return "<Book '%s' by %s>" % (self.name, self.authors) 
+0

'models.book.new'不會使用您開始的會話,這是立即創建新模型的便捷方法。 –

1

最好的(最有效的)方法是代碼如下:

authors = t1.saved['author'] 

with models.session().begin() as t1: 
    for author in ['Leo Tolstoy', 'unknown ghostwriter']: 
     t1.add(models.author(name=author)) 
    publisher = t1.add(models.publisher(name='Penguin Books')) 

在這一點上,作者和出版商都省了,除了作者可以從交易saved屬性檢索

現在,您可以創建書:

with models.session().begin() as t2: 
    for title in ['Anna Karenina', 'War and Peace']: 
     t2.add(models.book(name=title, publisher=publisher)) 

現在你可以通過最後一個事務添加作者:

books = t2.saved['book'] 

with models.session().begin() as t3: 
    for book in books: 
     # add the book to the transaction 
     t3.add(book) 
     for author in authors: 
      book.authors.push_back(author) 

所有上面的代碼假設你正在使用此模型的定義:

import sys 

from stdnet import odm 

class Publisher(odm.StdModel): 
    name = odm.SymbolField() 

    def __unicode__(self): 
     return self.name 

class Author(odm.StdModel): 
    name = odm.SymbolField() 

    def __unicode__(self): 
     return self.name 

class Book(odm.StdModel): 
    name = odm.CharField() 
    authors = odm.ListField(model=Author) 
    publisher = odm.ForeignKey(Publisher, related_name='publishers') 


    def __unicode__(self): 
     return "<Book '%s' by %s>" % (self.name, self.authors)