如何为 Django 创建一个唯一的随机用户名?

How to create a unique random username for django?

我希望我页面的访问者无需先注册即可创建条目。当他们稍后注册时,我希望他们在该会话中创建的所有内容都属于他们的用户帐户。

为了实现这一点,我只想在非用户输入时创建具有随机用户名的空白用户。

随机创建唯一用户名避免任何冲突的最优雅方法是什么?

我应该做一个 while 循环来生成用户名并在成功时尝试将它们保存到数据库中,还是有更好的方法?

我见过的大多数脚本只是创建一个随机字符串,但这有发生冲突的危险。是否有任何 Django 函数可以根据已使用的用户名创建随机用户名?

不,django 没有这样的功能。所以你必须在循环中检查生成的用户名是否存在。

我创建了一个 mixin,它根据名字、姓氏创建一个随机用户名,并确保该用户名不存在于数据库用户模型中:

random_username_mixin.py

import random
import string

from core.models import CustomUser


class RandomUsernameMixin:
    """
    using firstname & lastname
    create a random username (all lower case)
    that doesnt already exist in db
    """
    num_of_random_letters = 3
    num_of_random_numbers = 2
    user_model = CustomUser

    def get_username(self, firstname=None, lastname=None):
        username = ''
        if firstname and lastname \
                and firstname != '' and lastname != '':
            username = firstname[0] + lastname[0]

        while True:
            random_letters = string.ascii_lowercase
            random_numbers = string.digits
            username += self.get_random_char(
                random_letters, self.num_of_random_letters
            )
            username += self.get_random_char(
                random_numbers, self.num_of_random_numbers
            )
            if self.username_exist_in_db(username) is False:
                return username

    def username_exist_in_db(self, username):
        """
        :return: True if username already exist in db
            else False
        """
        q = self.user_model.objects.filter(username=username)
        return q.exists()

    def get_random_char(self, ip_str, n):
        return (''.join(
            random.choice(ip_str)
            for i in range(n)
        ))

以下为测试代码。它测试上面的代码:

test_random_username_mixin.py

from django.test import TestCase

from miscellaneous.mixins.random_username_mixin import RandomUsernameMixin


class TestRandomUsernameMixin(RandomUsernameMixin,
                              TestCase):

    def test_username_with_fn_ln(self):
        fn = 'aseem'
        ln = 'hegshetye'
        username = self.get_username(
            firstname=fn, lastname=ln
        )
        len_of_initials = 2
        len_of_username = self.num_of_random_numbers + \
                          self.num_of_random_letters + \
                          len_of_initials
        self.assertEqual(len(username), len_of_username)
        print(username)

    def test_username_without_fn_ln(self):
        username = self.get_username()
        len_of_initials = 0
        len_of_username = self.num_of_random_numbers + \
                          self.num_of_random_letters + \
                          len_of_initials
        self.assertEqual(len(username), len_of_username)
        print(username)