2014-06-20 43 views
2

我需要創建用戶使他的名字獨特的邏輯小的幫助:Django的 - 創造用戶使他們的全名唯一

我有一個Django的用戶配置文件。我以這種方式創建用戶:

fullname = request.POST.get('fullname') 
random_username = ''.join(random.sample(string.ascii_lowercase, 8)) 
new_user = User.objects.create_user(random_username, email, passwort) 
##update siteprofile of this new user 
userprofile = new_user.get_profile() 

""" 
    i need to make this fullname unique with this logic: 
    for example john is the fullname of new user. i need to check if there are 
    other johns in db, if there is another user with this name, i will name the 
    user with 'john1'. if there are 2, the new user will get the name 'john3' 
    how can I check this in db in some efficient way? 

""" 
userprofile.name = fullname 
userprofile.save() 

回答

2

您要檢查IntegrityError保存並相應更新。執行查詢來檢查名稱是否存在會創建一個競爭條件,您可以在其中搜索兩個單獨的線程,並嘗試同時創建相同的全名。

from django.db import transaction 

@transaction.commit_manually 
def set_fullname(userprofile, fullname, i=0): 
    new_fullname = u"{}{}".format(fullname, str(i) if i else '') 
    try: 
     userprofile.fullname = new_fullname 
     userprofile.save() 

     transaction.commit() 

     return userprofile 
    except IntegrityError: 
     transaction.rollback() 

     i += 1 
     # Just recursively try until we a valid name. This could be problematic if you 
     # have a TON of users, but in that case you could just the filter before then to see 
     # what number to start from. 
     return set_fullname(userprofile, fullname, i) 

userprofile = set_fullname(userprofile, fullname) 
+0

非常好,這確保來自世界2個地區的兩個人不會設置相同的名稱,對吧? – doniyor

+0

這是正確的。並且它在數據庫級別執行,所以您不會遇到兩個線程同時設置相同名稱的難得機會。 – sdolan

+0

''userprofile.fullname = fullname''應該是''userprofile.fullname = new_fullname'',對吧? – doniyor

1

爲此,最好使用表格https://docs.djangoproject.com/en/dev/topics/forms/。但是,如果你不會使用形式,你可以這樣做的:

i = 0 
orig_fullname = fullname 
created = False 
while not created: 
    profile, created = UserProfile.objects.get_or_create(name=fullname) 
    if not created: 
     i+=1 
     fullname = orig_fullname + str(i) 
# there you have new user's profile 

注意,在用戶配置模型場「名」必須具有唯一= true參數https://docs.djangoproject.com/en/dev/ref/models/fields/#unique

+0

聽起來不錯。之後,我真的會得到最新的全名嗎? – doniyor

+0

您想嘗試插入它並捕獲IntegrityError,因此唯一性是在db級別處理的,並且您避免了競爭條件。 – sdolan

+0

@ doniyor只是把它扔進一個答案更容易 – sdolan