Уникальное образцовое поле в Django и чувствительности к регистру (пост-ГРЭС)

Невозможно сделать это в одном запросе. Вы должны искать документ в первом запросе:

Если существует документ:

db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } , 
                {$inc : {"items.$.price" : 1} } , 
                false , 
                true);

Else

db.bar.update( {user_id : 123456 } , 
                {$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
                false , 
                true);

Не нужно добавлять условие {$ne : "my_item_two" } .

Также в многопоточной среде вы должны быть осторожны, чтобы только один поток мог выполнить второй (вставить регистр, если документ не был найден) за раз, в противном случае будут вставлены дублирующие вложенные документы.

25
задан chefsmart 7 December 2009 в 04:31
поделиться

5 ответов

Вы можете определить поле пользовательской модели, полученное из models.CharField. Это поле может проверять дубликаты значений, игнорируя регистр.

Документация по настраиваемым полям находится здесь http://docs.djangoproject.com/en/dev/howto/custom-model-fields/

Посмотрите на http: / /code.djangoproject.com/browser/django/trunk/django/db/models/fields/files.py для примера того, как создать настраиваемое поле путем создания подкласса существующего поля.

Вы можете использовать модуль citext в PostgreSQL https://www.postgresql.org/docs/current/static/citext.html

Если вы используете этот модуль, Пользовательское поле может определять «db_type» как CITEXT для баз данных PostgreSQL.

Это привело бы к нечувствительному к регистру сравнению уникальных значений в настраиваемом поле.

29
ответ дан MichielB 15 October 2019 в 15:44
поделиться

Со стороны Postgres функциональный уникальный индекс позволит вам применять уникальные значения без регистра. Также отмечается citext, но он будет работать со старыми версиями PostgreSQL и в целом полезен.

Пример:

# create table foo(bar text);
CREATE TABLE
# create unique index foo_bar on foo(lower(bar));
CREATE INDEX
# insert into foo values ('Texas');
INSERT 0 1
# insert into foo values ('texas');
ERROR:  duplicate key value violates unique constraint "foo_bar"
6
ответ дан Alex Brasetvik 15 October 2019 в 15:44
поделиться

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

class State(models.Model):
    name = models.CharField(max_length=50, unique=True)

    def save(self, force_insert=False, force_update=False):
        self.name = self.name.lower()
        super(State, self).save(force_insert, force_update)
3
ответ дан Michal Čihař 15 October 2019 в 15:44
поделиться

Решение от suhail работало для меня без необходимости включать citext, довольно простое решение, только чистая функция и вместо заглавных букв я использовал upper(). Решение Маюреша также работает, но изменило поле с CharField на TextField.

class State(models.Model):

    name = models.CharField(max_length=50, unique=True)

    def clean(self):
        self.name = self.name.upper()
0
ответ дан nymk 15 October 2019 в 15:44
поделиться

Вы можете сделать это, перезаписав метод сохранения модели - см. docs . В основном вы бы сделали что-то вроде:

class State(models.Model):
    name = models.CharField(max_length=50, unique=True)

    def save(self, force_insert=False, force_update=False):
        if State.objects.get(name__iexact = self.name):
            return
        else:
            super(State, self).save(force_insert, force_update)

Кроме того, я могу ошибаться в этом, но предстоящая ветвь SoC для проверки модели позволит нам сделать это проще.

1
ответ дан 28 November 2019 в 06:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: