如何检查数据库中是否已存在模型实例

时间:2017-09-21 14:07:51

标签: python django

所以我定义了一个模型Language。我需要跟踪创建语言对象的人。我也不需要同一种语言的多个实例。出于这个原因,我希望能够在用户尝试创建语言时检查语言是否已存在。如果它存在,那么我只是告诉用户他们可以使用已存在的那个。如果没有,他们可以创建它。我使用的是自定义User模型。

USERS = get_user_model().objects.all()
from random import choice

class Language(models.Model):
    language = models.CharField(max_length=25, unique=True)
    creator = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    def __str__(self):
        return self.language

    def get_absolute_url(self):
        return reverse('chinemerem:language_index')

    def save(self, *args, **kwargs):
        self.language = self.language.upper()
        super(Language, self).save(*args, **kwargs)

我可以在Language try/except中使用django创建shell个实例,如下所示。

try:
    language, exists = Language.objects.get_or_create(creator=choice(USERS),
                                language='german')
except IntegrityError:
    pass

但是当我尝试通过django admin创建语言实例时,django admin会抛出IntegrityError

我的问题:如何在我的模型中实现类似上面try/except块的内容,以检查当用户尝试创建语言时是否已存在某种语言?

我已经做了很多搜索,并且遇到了来自signals的pre_save,我怀疑这可能会有所帮助。但是django文档的例子非常少。

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

Your problem comes from the way you call get_or_create() - 您将这两个字段作为查询参数传递,因此它首先尝试使用Language language='german'查找creator=<youruserhere>。如果存在相同的语言但具有不同的创建者,则它与where子句不匹配,因此orm尝试创建新记录,然后language上的唯一约束开始。< / p>

解决方案是将creator作为defaults参数传递到dict中,以便仅在language上进行查找,creator仅用于创建新记录。必要的:

language, created = Language.objects.get_or_create(
   # this is used for lookup (get)
   language="german", 
   # this is used for eventual create
   defaults={'creator':choice(USERS)}
   )

作为旁注,如果已创建新记录,则返回元组的第二个元素将为True,如果找到已存在的记录,则为False

wrt /管理员中的问题,除非您在ModelAdmin或其表单中做了一些奇怪的事情,或者您没有发布整个模型代码,它应该重新显示表单一条错误消息,不会引发IntegrityError(除非最终在表单验证和实例保存之间遇到竞争条件,但这应该非常非常罕见)。验证期间的唯一性检查是ModelForm的默认功能,因此我不能应用它的唯一原因(我能想到)将覆盖您的表单clean()方法而不调用super().clean()。< / p>

答案 1 :(得分:0)

您可以使用exists方法

getLanguage = Language.objects.filter(language=request['langugage']).exists()

if not getLanguage:
 # create the model

答案 2 :(得分:0)

感谢大家。以下是我使用模型管理器解决问题的方法。

我使用了两个模特经理。我使用objects = models.Manager()作为模型管理员之一,因此我不需要重写我的大量代码。

from django.db import models
class LanguageManager(models.Manager):
    def language_exists(self, language):
        return super(LanguageManager, self).get_queryset().filter(language=language.upper()).exists()

class Language(models.Model):
    creator = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    language = models.CharField(max_length=25, unique=True)
    objects = models.Manager()
    languages = LanguageManager()

    def __str__(self):
        return self.language

    def get_absolute_url(self):
        return reverse('chinemerem:language_index')

    def save(self, *args, **kwargs):
        self.language = self.language.upper()
        if Language.languages.language_exists(self.language):
            return "Language already exists."
        else:
            super(Language, self).save(*args, **kwargs)