我正在试验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
值?
和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 作者的评论中有回应。我认为他基本上和我说的是同样的话,但你可以自己阅读。
最好(最有效(的方法是按如下方式编码:
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)