ValueError при доступе к таблице после вставки объекта ROW в список: поле ссылки - PullRequest
2 голосов
/ 26 февраля 2012

Я получаю ValueError для запроса DAL db(db.posts.id == request.vars["post"]).select().first() со следующим TraceBack:

Traceback (most recent call last):
  File "E:\Programming\Python\web2py\gluon\restricted.py", line 204, in restricted
    exec ccode in environment
  File "E:/Programming/Python/web2py/applications/vote_up/controllers/default.py", line 109, in <module>
  File "E:\Programming\Python\web2py\gluon\globals.py", line 172, in <lambda>
    self._caller = lambda f: f()
  File "E:/Programming/Python/web2py/applications/vote_up/controllers/default.py", line 67, in vote
    if request.vars["post"]:    var = db(db.posts.id == request.vars["post"]).select().first()
  File "E:\Programming\Python\web2py\gluon\dal.py", line 6333, in select
    return self.db._adapter.select(self.query,fields,attributes)
  File "E:\Programming\Python\web2py\gluon\dal.py", line 1287, in select
    return self.parse(rows,self._colnames)
  File "E:\Programming\Python\web2py\gluon\dal.py", line 1533, in parse
    colset[fieldname] = bar_decode_integer(value)
  File "E:\Programming\Python\web2py\gluon\dal.py", line 4408, in bar_decode_integer
    return [int(x) for x in value.split('|') if x.strip()]
ValueError: invalid literal for int() with base 10: "<Row {'joined': datetime.datetime(2012, 2, 26, 17, 42, 26), 'password': 'SS', 'id': 1, 'name': 'a', 'reputation': 0}>"

Это произошло после того, как я изменил свой контроллер на:

def vote():
    '''Add a vote'''
    path_to=session.path_to
    if request.vars["post"]:    var = db(db.posts.id == request.vars["post"]).select().first()
    elif request.vars["answer"]:    var = db(db.answers.id == request.vars["answer"]).select().first()
    elif request.vars["comment"]:    var = db(db.comments.id == request.vars["comment"]).select().first()
    elif request.vars["comment_r"]:    var = db(db.comments_r.id == request.vars["comment_r"]).select().first()
    else: return None
    inc = 0
    if int(request.vars["up"])==1:
        inc=1
        if not var.v_up:    var.v_up = []
        if session.user in var.v_up:    return var.votes
        var.update_record(
            votes=var.votes+inc,
            v_up = var.v_up+[session.user]
        )
    elif int(request.vars["up"])==0:
        inc=-1
        if not var.v_dn:    var.v_dn = []
        if session.user in var.v_dn:    return var.votes
        var.update_record(
            votes=var.votes+inc,
            v_dn = var.v_dn+[session.user]
        )
    return var.votes

The session.user - это объект ROW пользовательской таблицы, например:

<Row {'joined': datetime.datetime(2012, 2, 26, 17, 42, 26), 'password': 'SS', 'id': 1, 'name': 'a', 'reputation': 0}>

Таблицы структурированы следующим образом:

db.define_table('posts', 
    db.Field('title', 'string'),
    db.Field('message', 'text'),
    db.Field('user', 'reference users'),
    db.Field('votes', 'integer', default=0),
    db.Field('v_up', 'list:reference users'),
    db.Field('v_dn', 'list:reference users'),
    db.Field('time', 'datetime', default=datetime.utcnow())
)

db.define_table('users',
    db.Field('name', 'string'),
    db.Field('password', 'password'),
    db.Field('reputation', 'integer', default=0),
    db.Field('joined', 'datetime', default=datetime.utcnow())
)

Я снова что-то упустил?

ОБНОВЛЕНИЕ: Похоже, таблица posts повреждена, поскольку я получаю ту же ошибку ValueError даже для print db(db.posts).select().Может ли v_up = var.v_up+[session.user] повредить таблицу?Зачем?И есть ли способ его восстановить?

ОБНОВЛЕНИЕ: Подтверждено, что v_up = var.v_up+[session.user] портит таблицу.Как правильно использовать поле list:refernce?

1 Ответ

2 голосов
/ 27 февраля 2012

Поле list:refernce в DAL является прославленным полем со списком целых чисел, в котором хранятся идентификаторы строк в указанной таблице.

Поэтому, когда вы вставляете объект ROW в это поле, это вызывает ValueError, поскольку объект ROW не является целочисленным идентификатором из таблицы.

Чтобы исправить это, замените объект session.user ROW его целочисленным идентификатором, session.user.id.

Вот пример из Web2Py book :

>>> db.define_table('tag',Field('name'),format='%(name)s')
>>> db.define_table('product',
        Field('name'),
        Field('tags','list:reference tag'))
>>> a = db.tag.insert(name='red')
>>> b = db.tag.insert(name='green')
>>> c = db.tag.insert(name='blue')
>>> db.product.insert(name='Toy Car',tags=[a, b, c])
>>> products = db(db.product.tags.contains(b)).select()
>>> for item in products:
        print item.name, item.tags
Toy Car [1, 2, 3]
>>> for item in products:
        print item.name, db.product.tags.represent(item.tags)
Toy Car red, green, blue

Обратите внимание, что метод insert возвращает идентификатор вставленной строки.

...