首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于Weppy/pyDal中另一列限制数据库插入的最佳方法?

基于Weppy/pyDal中另一列限制数据库插入的最佳方法?
EN

Stack Overflow用户
提问于 2016-06-10 03:45:35
回答 1查看 79关注 0票数 0

如果同一个用户已经有一个具有相同名称的项,我希望限制特定表的DB插入。

代码语言:javascript
复制
Table
_____________
user     | place         | label     |
--------------------------------------------------------------------------
me       | san francisco | work      |
you      | san francisco | leisure   | # This is ok because different user
me       | san francisco | leisure   | # THIS IS NOT ALLOWED - INSERT FAIL

标签对用户来说是唯一的,所以我不想强迫"name“列成为唯一的->,许多用户应该能够添加相同的位置,但是在标签列中添加任何”标签“。

注意:使用温皮 -我没有足够的声誉来创建一个新的标签。一旦我能/有一个模糊的标签,我就给这个问题贴标签。

我已经找到了一个解决办法,这似乎是太多的代码。需要使用Place().add_new()而不是内置的pyDal方法:

代码语言:javascript
复制
from weppy.dal import Model, Field, belongs_to


class Place(Model):
    belongs_to('user')

    name = Field() # not using `unique=True` here so others can insert same names.
    label = Field()

    def add_new(self, user_id, name, label):
        user_places = self.db(self.db.Place.user == user_id).select()
        current_names = [x.name for x in user_places]
        if name not in current_names:
            self.create(
                user=user_id,
                name=name,
                label=label
            )
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-10 09:35:05

关于唯一性的复杂之处在于,您不能确定仅在并发环境(如web应用程序)中使用应用程序代码就可以尊重它。

例如,如果同一个用户将产生两个并发请求--在这种情况下可能不太可能,但您应该知道--那么应用程序代码可能会失败,因为可以在检查和另一个插入之间插入具有相同值的记录。

这就是为什么您应该首先依赖数据库本身,并且由于weppy0.7,您可以使用数据库索引

代码语言:javascript
复制
class Place(Model):
    belongs_to('user')

    name = Field()
    label = Field()

    indexes = {
        'user_uniq_name': {
            'fields': ['user', 'name'], 'unique': True}
    }

只需记住在添加索引后生成迁移。

一旦有了带有唯一约束的索引,就可以将新记录的创建包装在try-except块中:

代码语言:javascript
复制
try:
    rv = Place.create(**some_params)
except:
    # handle the error eg:
    from weppy import abort
    abort(422)

当然,您仍然可以在插入之前保留一些应用程序检查,但是由于您需要检查多个值,并且自定义验证器只支持一个值(除非使用会话检查用户),所以最好使用回调

代码语言:javascript
复制
from weppy.dal import before_insert

class Place(Model):
    @before_insert
    def check_name_uniqueness(self, input_fields):
        if self.db(
            (self.user == input_fields['user']) &
            (self.name == input_fields['name'])
        ).count() > 0:
            return True
        return False

从医生那里:

所有回调方法都应该返回None或False ( python中不返回任何内容与返回None相同),否则返回True将中止当前操作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37739540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档