2016-12-05 105 views
1

使用Django 1.10我想在用戶名中允許\字符,因爲我在使用'django.contrib.auth.middleware.RemoteUserMiddleware'的Windows環境中工作,並且遠程用戶作爲域\用戶名(我不想刪除域在某些業務邏輯中使用)。Django覆蓋ASCIIUsernameValidator

我可以通過修改行regex = r'^[\[email protected]+-]+$'改變Django的\的contrib \權威性\ validators.py容易夠了,都希望的影響是regex = r'^[\[email protected]+-\\]+$'不過,我認爲一個可以很容易地覆蓋這個類,但我失敗了。

我發現一些有用的鏈接(和許多其他類似這裏SO):

https://stackoverflow.com/a/39820162/4872140

https://stackoverflow.com/a/1214660/4872140

https://docs.djangoproject.com/en/1.10/releases/1.10/#official-support-for-unicode-usernames https://docs.djangoproject.com/en/1.10/ref/contrib/auth/#django.contrib.auth.models.User.username_validator

但信息是過時的,或者沒有按不完全顯示/完全如何解決我的問題(在最後兩個的情況下)。我很喜歡這款應用,所以改變AUTH_USER_MODEL並不吸引人。 settings.py:

AUTH_USER_MODEL = 'myapp.MyUser' 

無論如何我嘗試了,想我或許可以對用戶模型等,其導致錯誤以下使用代理服務器「不能代理的交換模式‘myapp.DomainUser’」:

class DomainASCIIUsernameValidator(ASCIIUsernameValidator): 
    regex = r'^[\[email protected]+-\\]+$' 

class DomainUser(User): 
    username_validator = DomainASCIIUsernameValidator() 

    class Meta: 
     proxy = True 

是否有一種方法可以用戶模型保持不變的方式在ASCIIUsernameValidator(和UnicodeUsernameValidator)中替換正則表達式。如果您按照https://docs.djangoproject.com/en/1.10/ref/contrib/auth/#django.contrib.auth.models.User.username_validator中所描述的方式對用戶模型進行子類化,您是否堅持在AUTH_USER_MODEL中指定該模型?

我已閱讀https://groups.google.com/forum/#!topic/django-developers/MBSWXcQBP3k/discussion的討論,感覺從一開始就創建自定義用戶可能會成爲默認情況。

回答

4

我花了一整天的時間和許多不同的答案來得到這個工作。我將代碼分成不同的部分。首先,我們有我們的驗證:

validators.py

from django.contrib.auth.validators import UnicodeUsernameValidator 
from django.utils.translation import ugettext_lazy as _ 


class DomainUnicodeUsernameValidator(UnicodeUsernameValidator): 
    """Allows \.""" 
    regex = r'^[\[email protected]+-\\]+$' 
    message = _(
     'Enter a valid username. This value may contain only letters, ' 
     'numbers, and \/@/./+/-/_ characters.' 
    ) 

我加改變的消息也說\是允許的。您也可以輕鬆添加DomainASCIIUsernameValidator。

models.py

from django.contrib.auth.models import User 

from .validators import DomainUnicodeUsernameValidator 


class DomainUser(User): 
    class Meta: 
     proxy = True 

    def __init__(self, *args, **kwargs): 
     self._meta.get_field(
      'username' 
     ).validators[0] = DomainUnicodeUsernameValidator() 

     super().__init__(*args, **kwargs) 

這抓住了我們之前設置的驗證。它還代理默認用戶併爲用戶名字段設置驗證器。您可以設置驗證器作爲一個列表,包括新的驗證和最大長度校驗(這可能是在情況下,爲了改變更安全)。

forms.py

from django.contrib.auth.forms import UserChangeForm 
from django.utils.translation import ugettext_lazy as _ 

from .models import DomainUser 


class DomainUserChangeForm(UserChangeForm): 
    class Meta(UserChangeForm.Meta): 
     model = DomainUser 
     help_texts = { 
      'username': _('Required. 150 characters or fewer. Letters, digits and \/@/./+/-/_ only.'), # NOQA 
     } 

在這裏,我延長UserChangeForm和設置模式,使用用戶名驗證變更代理模型。

如果您希望允許用戶使用\添加用戶名,那麼您還需要以類似的方式更改UserAddForm。

最後,在admin.py

from django.contrib import admin 
from django.contrib.auth.admin import UserAdmin 
from django.contrib.auth.models import User 

from .forms import DomainUserChangeForm 


class DomainUserAdmin(UserAdmin): 
    form = DomainUserChangeForm 


admin.site.unregister(User) 
admin.site.register(User, DomainUserAdmin) 

我們設定的形式爲我們的管理員將在Django管理頁面中使用。然後取消設置用戶管理,並將其替換爲我們的自定義DomainUserAdmin。

+0

哇!我剛剛開始一個新項目,我會在第二天左右通過這個項目給大家一個鏡頭。 – AMG

+0

如果您要開始一個新項目,我會建議創建一個新的用戶模型。他們甚至推薦它[鏈接](https://docs.djangoproject.com/zh/dev/topics/auth/customizing/#substotation-a-custom-user-model): _如果你正在開始一個新項目,強烈建議設置一個自定義用戶模型,即使默認的用戶模型對您來說已經足夠。此模型的行爲與默認用戶模型的行爲相同,但如果需要,您可以在將來自定義它:_。 –