我正在尝试使用stdnet,而我正面临一个应该是一个相对简单的案例的挑战。
如果我填充我的模型(参见下面的<hr>
)而没有指定主键的值,我得到:
stdnet.utils.exceptions.FieldValueError:{“author_id”:'main.book'需要“字段'author_id'。”}
author1 = models[Author](name='Jeff Doyle')
但是,为id
添加一个值会使代码工作......
author1 = models[Author](name='Jeff Doyle', id=1)
Author.id
是odm.AutoIdField()
。由于这是一个分层数据模型,我可能能够理解手动将id = odm.AutoIdField()
添加到我的模型的要求。但是,文档说odm.AutoIdField会自动生成主键的值。
我的问题:为什么在填充模型时需要手动为id
指定值?
我在Python 2.6.6和Debian 6.0(内核2.6.32-5-amd64)上运行stdnet 0.8.2 w / Cython。
工作实例:
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'."}
我认为问题是你试图在同一个会话中插入书和作者。因此,在提交时,作者尚未保存到数据库中,因此没有用于在外键中引用的书的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。我认为他基本上和我说同样的话,但你可以自己阅读。
最好(最有效)的方法是编码如下:
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
属性中检索:
authors = t1.saved['author']
您现在可以创建书籍:
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)
首先我不知道图书馆(我实际上一直在寻找这个,所以谢谢:))。我认为models.register
不仅会在您的程序中注册模型,还会在Redis服务器上注册。所以你要么必须清除数据库,要么找到改变模型的方法。
希望能帮助到你
我使用不同于James Holderness推荐的语法结束了;他的回答很有帮助,但我在原始问题中使用的语法似乎不适用于复杂的odm.ForeignKey
模型。我最终切换到不同的语法,我在这里记录,因为python-stdnet 0.8
文档有点令人困惑。
构建数据库:
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
查询数据库:
## 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)