所以我定义了一个模型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文档的例子非常少。
任何帮助将不胜感激。
答案 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)