redis / stdnet数据模型回溯

问题描述 投票:3回答:4

我正在尝试使用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.idodm.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'."}
python redis nosql
4个回答
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。我认为他基本上和我说同样的话,但你可以自己阅读。


1
投票

最好(最有效)的方法是编码如下:

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)

0
投票

首先我不知道图书馆(我实际上一直在寻找这个,所以谢谢:))。我认为models.register不仅会在您的程序中注册模型,还会在Redis服务器上注册。所以你要么必须清除数据库,要么找到改变模型的方法。

希望能帮助到你


0
投票

我使用不同于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)
© www.soinside.com 2019 - 2024. All rights reserved.