Как да направя многоколонни уникални ограничения на ниво база данни в web2py?

Ако имам нещо подобно в моя models/db.py:

   db.define_table('magazine', Field('name'), Field('description'))
   db.define_table('subscribe', Field('subscriber', db.auth_user), Field('magazine', db.magazine))

И в controller/default.py:

# subscribe callback from view
@auth.requires_login()
def subscribe():
    mag_id = request.args(0, cast=int)
    db.subscribe.insert(magazine=mag_id, subscriber=auth.user.id)

Потребителят ще щракне върху бутон за абониране, който трябва да извика обратното извикване и да вмъкне потребителя в таблицата за абониране с текущото списание, което гледа.

Как да накарам таблицата за абониране да съдържа уникални комбинации от абонат и списание? Абонат, който се е абонирал за списание, не трябва да може да се абонира отново за същото списание.

Например, това трябва да работи:

Потребител 1, Списание 1
Потребител 1, Списание 2
Потребител 2, Списание 1

Но това не трябва:

Потребител 1, Списание 1
Потребител 1, Списание 1

Едно решение беше ръчната проверка дали комбинацията вече съществува в моя контролер:

def subscribe():
    mag_id = request.args(0, cast=int)
    subscribed = db(db.subscribe.subscriber==auth.user.id)&(db.subscribe.magazine==mag_id))

    if len(subscribed) < 1:
        # Do insert
    else:
        # Do nothing, user is already subscribed.

Но има ли по-добър начин (за предпочитане на ниво база данни) да направите това? Четох, че използването на IS_NOT_IN_DB() може да работи, но изглежда е ограничено до използване на формуляри? Тази тема също предполага, че няма да работи .


person Bak    schedule 01.05.2013    source източник


Отговори (1)


DAL не предоставя начин за указване на ограничение за уникалност с няколко колони в базата данни, но можете да направите това директно в базата данни извън web2py. Въпреки това, вероятно все още искате някакъв явен код в приложението, който да се справи с това - в противен случай нарушение на ниво база данни просто ще доведе до генериране на изключение. В този случай можете просто да използвате метода .update_or_insert():

db.subscribe.update_or_insert(magazine=mag_id, subscriber=auth.user.id)

Това ще направи вмъкването само ако вече не съществува запис с това списание и абонат.

person Anthony    schedule 01.05.2013
comment
О, това е много удобно. Благодаря ви, това вероятно ще свърши работа. - person Bak; 01.05.2013