我的用户个人资料模型中有一个uniqname
字段。逻辑是:如果新用户的名称是john
,并且如果db中有其他john,则新john应该得到名称john1
。如果在db中有2个johns,则新john应该得到john3
。
我尝试使用此代码实现此目的:
def set_uniqname(userprofile, fullname, i=0):
new_uniqname = u"{}{}".format(fullname, str(i) if i else '')
try:
userprofile.uniqname = new_uniqname
userprofile.save()
return userprofile
except IntegrityError:
i += 1
return set_uniqname(userprofile, fullname, i)
name = request.POST.get('name').title()
email = request.POST.get('email')
passwort = request.POST.get('passwort')
""" create base django user with random username """
random_username = ''.join(random.sample(string.ascii_lowercase, 26))
new_user = User.objects.create_user(random_username, email, passwort)
""" update the created userprofile with unique fullname for URL """
userprofile = new_user.get_profile()
uniqname = name.replace(' ','')
userprofile = set_uniqname(userprofile, uniqname)
但是我收到了错误:
current transaction is aborted, commands ignored until end of transaction block
用户配置文件中的uniqname字段以这种方式定义:
uniqname = models.TextField(unique=True, default=None, null=True)
我在post_save信号中将此字段设置为None
,以便我可以在create_account方法中将其设置为uniqname:
def create_profile(sender, **kw):
user = kw["instance"]
if kw["created"]:
up = Person(user=user)
up.uniqname = None
up.save()
post_save.connect(create_profile, sender=User)
为什么我会收到此错误以及如何实现此目标的任何想法?
答案 0 :(得分:2)
问题是您的数据库抛出IntegrityError
并且您没有在数据库级别处理异常。您必须将当前事务回滚到没有错误的点。由于您可能不希望回滚到封装整个视图的事务的开头,因此您需要在atomic
块中运行代码。然后你就可以回滚这个特定的陈述:
from django.db import transaction
def set_uniqname(userprofile, fullname, i=0):
new_uniqname = u"{}{}".format(fullname, str(i) if i else '')
try:
with transaction.atomic():
userprofile.uniqname = new_uniqname
userprofile.save()
return userprofile
except IntegrityError:
i += 1
return set_uniqname(userprofile, fullname, i)
atomic()
将在块的开头自动创建一个保存点,当块成功时,将其提交到数据库。如果抛出错误,则块将回滚到保存点,并允许错误向上传播到try
块。
答案 1 :(得分:0)
在我看来,你可以从'YourModel'覆盖save()方法。这是我的想法的例子。
def _get_unique_name(self, name, count=0):
"""
Method returns unique name.
"""
try:
name = YourModel.objects.get(name=name)
count = count + 1
name = "%s%s" % (name, count)
self._get_unique_name(name, count) #recursion
except:
return name
def save(self, *args, **kwargs):
"""
Overides save method from YourModel.
"""
self.name = self._get_unique_name(self.name)
super(YourModel, self).save(*args, **kwargs)
你必须尝试这个..也许有一些错误。我没有测试它。它直接来自我的脑海:)
您应该在模型类中执行此操作。