Django에서 이메일 주소를 사용자 이름으로 수락
내 자신의 인증 시스템을 롤링하지 않고 django에서 이것을 수행하는 좋은 방법이 있습니까? 사용자 이름을 만드는 대신 사용자 이름을 사용자의 이메일 주소로 사용하고 싶습니다.
조언 부탁드립니다, 감사합니다.
이 작업을 수행하려는 다른 사람에게는 django-email-as-username 을 살펴 보는 것이 좋습니다.이 솔루션은 관리자 및 createsuperuser
관리 명령 패치를 포함하는 매우 포괄적 인 솔루션 입니다.
편집 : Django 1.5부터 django-email-as-username 대신 사용자 정의 사용자 모델을 사용하는 것을 고려해야 합니다.
여기에 우리가하는 일이 있습니다. "완전한"솔루션은 아니지만 원하는 기능을 많이 수행합니다.
from django import forms
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
exclude = ('email',)
username = forms.EmailField(max_length=64,
help_text="The person's email address.")
def clean_email(self):
email = self.cleaned_data['username']
return email
class UserAdmin(UserAdmin):
form = UserForm
list_display = ('email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff',)
search_fields = ('email',)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
다음은 사용자 이름과 이메일이 모두 허용되도록하는 한 가지 방법입니다.
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.forms import ValidationError
class EmailAuthenticationForm(AuthenticationForm):
def clean_username(self):
username = self.data['username']
if '@' in username:
try:
username = User.objects.get(email=username).username
except ObjectDoesNotExist:
raise ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
params={'username':self.username_field.verbose_name},
)
return username
기본 인증 양식을 설정하는 설정이 있는지 모르겠지만 urls.py에서 URL을 재정의 할 수도 있습니다.
url(r'^accounts/login/$', 'django.contrib.auth.views.login', { 'authentication_form': EmailAuthenticationForm }, name='login'),
ValidationError를 발생 시키면 유효하지 않은 이메일이 제출 될 때 500 오류를 방지 할 수 있습니다. "invalid_login"에 대한 super의 정의를 사용하면 이메일 주소가 귀하의 서비스 계정에 등록되었는지 여부를 유출하는 것을 방지하는 데 필요한 오류 메시지가 모호하게 유지됩니다 (특정 "해당 이메일로 사용자가 없음"과 비교). 해당 정보가 아키텍처에서 안전하지 않은 경우 더 많은 정보를 제공하는 오류 메시지가있는 것이 더 편할 수 있습니다.
Django는 이제 관리자 및 양식이 포함 된 확장 인증 시스템의 전체 예제를 제공합니다. https://docs.djangoproject.com/en/stable/topics/auth/customizing/#a-full-example
기본적으로 복사 / 붙여 넣기 및 적용 할 수 있습니다 ( date_of_birth
제 경우에는 필요하지 않음 ).
실제로 Django 1.5부터 사용 가능하며 현재까지 사용 가능합니다 (django 1.7).
사용자 모델을 확장하려는 경우 어쨌든 사용자 지정 사용자 모델을 구현해야합니다.
다음은 Django 1.8의 예입니다. 조금 필요 장고 1.7은 대부분 기본 형태 (단지에서 살펴 변화, 더 많은 작업을 비트 UserChangeForm
& UserCreationForm
에 django.contrib.auth.forms
- 당신은 1.7에서 필요하다고).
user_manager.py :
from django.contrib.auth.models import BaseUserManager
from django.utils import timezone
class SiteUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
today = timezone.now()
if not email:
raise ValueError('The given email address must be set')
email = SiteUserManager.normalize_email(email)
user = self.model(email=email,
is_staff=False, is_active=True, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password, **extra_fields):
u = self.create_user(email, password, **extra_fields)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
models.py :
from mainsite.user_manager import SiteUserManager
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
class SiteUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, blank=False)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
objects = SiteUserManager()
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
forms.py :
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from mainsite.models import SiteUser
class MyUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = SiteUser
fields = ("email",)
class MyUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = SiteUser
class MyUserAdmin(UserAdmin):
form = MyUserChangeForm
add_form = MyUserCreationForm
fieldsets = (
(None, {'fields': ('email', 'password',)}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser',)}),
('Groups', {'fields': ('groups', 'user_permissions',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2')}
),
)
list_display = ('email', )
list_filter = ('is_active', )
search_fields = ('email',)
ordering = ('email',)
admin.site.register(SiteUser, MyUserAdmin)
settings.py :
AUTH_USER_MODEL = 'mainsite.SiteUser'
다른 대안은 나에게 너무 복잡해 보이므로 사용자 이름, 이메일 또는 둘 다를 사용하여 인증하고 대소 문자 구분을 활성화 또는 비활성화 할 수있는 스 니펫을 작성했습니다. django-dual-authentication 으로 pip에 업로드했습니다 .
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.conf import settings
###################################
""" DEFAULT SETTINGS + ALIAS """
###################################
try:
am = settings.AUTHENTICATION_METHOD
except:
am = 'both'
try:
cs = settings.AUTHENTICATION_CASE_SENSITIVE
except:
cs = 'both'
#####################
""" EXCEPTIONS """
#####################
VALID_AM = ['username', 'email', 'both']
VALID_CS = ['username', 'email', 'both', 'none']
if (am not in VALID_AM):
raise Exception("Invalid value for AUTHENTICATION_METHOD in project "
"settings. Use 'username','email', or 'both'.")
if (cs not in VALID_CS):
raise Exception("Invalid value for AUTHENTICATION_CASE_SENSITIVE in project "
"settings. Use 'username','email', 'both' or 'none'.")
############################
""" OVERRIDDEN METHODS """
############################
class DualAuthentication(ModelBackend):
"""
This is a ModelBacked that allows authentication
with either a username or an email address.
"""
def authenticate(self, username=None, password=None):
UserModel = get_user_model()
try:
if ((am == 'email') or (am == 'both')):
if ((cs == 'email') or cs == 'both'):
kwargs = {'email': username}
else:
kwargs = {'email__iexact': username}
user = UserModel.objects.get(**kwargs)
else:
raise
except:
if ((am == 'username') or (am == 'both')):
if ((cs == 'username') or cs == 'both'):
kwargs = {'username': username}
else:
kwargs = {'username__iexact': username}
user = UserModel.objects.get(**kwargs)
finally:
try:
if user.check_password(password):
return user
except:
# Run the default password hasher once to reduce the timing
# difference between an existing and a non-existing user.
UserModel().set_password(password)
return None
def get_user(self, username):
UserModel = get_user_model()
try:
return UserModel.objects.get(pk=username)
except UserModel.DoesNotExist:
return None
장고 등록의 최신 버전은 멋진 사용자 정의를 허용하고 일을 할 수 - 문서를 여기 https://bitbucket.org/ubernostrum/django-registration/src/fad7080fe769/docs/backend-api.rst
if user_form.is_valid():
# Save the user's form data to a user object without committing.
user = user_form.save(commit=False)
user.set_password(user.password)
#Set username of user as the email
user.username = user.email
#commit
user.save()
완벽하게 작동합니다 ... 장고 1.11.4에서
아래 링크에서이 주제에 대한 흥미로운 토론을 찾을 수도 있습니다.
가장 쉬운 방법은 로그인보기에서 이메일을 기반으로 사용자 이름을 조회하는 것입니다. 이렇게하면 다른 모든 것을 그대로 둘 수 있습니다.
from django.contrib.auth import authenticate, login as auth_login
def _is_valid_email(email):
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
try:
validate_email(email)
return True
except ValidationError:
return False
def login(request):
next = request.GET.get('next', '/')
if request.method == 'POST':
username = request.POST['username'].lower() # case insensitivity
password = request.POST['password']
if _is_valid_email(username):
try:
username = User.objects.filter(email=username).values_list('username', flat=True)
except User.DoesNotExist:
username = None
kwargs = {'username': username, 'password': password}
user = authenticate(**kwargs)
if user is not None:
if user.is_active:
auth_login(request, user)
return redirect(next or '/')
else:
messages.info(request, "<stvrong>Error</strong> User account has not been activated..")
else:
messages.info(request, "<strong>Error</strong> Username or password was incorrect.")
return render_to_response('accounts/login.html', {}, context_instance=RequestContext(request))
In your template set the next variable accordingly, i.e.
<form method="post" class="form-login" action="{% url 'login' %}?next={{ request.GET.next }}" accept-charset="UTF-8">
And give your username / password inputs the right names, i.e. username, password.
UPDATE:
Alternatively, the if _is_valid_email(email): call can be replaced with if '@' in username. That way you can drop the _is_valid_email function. This really depends on how you define your username. It will not work if you allow the '@' character in your usernames.
I think the most quickly way is to create a form inherit from UserCreateForm
, and then override the username
field with forms.EmailField
. Then for every new registration user, they need to signon with their email address.
For example:
urls.py
...
urlpatterns += url(r'^signon/$', SignonView.as_view(), name="signon")
views.py
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django import forms
class UserSignonForm(UserCreationForm):
username = forms.EmailField()
class SignonView(CreateView):
template_name = "registration/signon.html"
model = User
form_class = UserSignonForm
signon.html
...
<form action="#" method="post">
...
<input type="email" name="username" />
...
</form>
...
Not sure if people are trying to accomplish this, but I found nice (and clean) way to only ask for the email and then set the username as the email in the view before saving.
My UserForm only requires the email and password:
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('email', 'password')
Then in my view I add the following logic:
if user_form.is_valid():
# Save the user's form data to a user object without committing.
user = user_form.save(commit=False)
user.set_password(user.password)
#Set username of user as the email
user.username = user.email
#commit
user.save()
참고URL : https://stackoverflow.com/questions/778382/accepting-email-address-as-username-in-django
'Programing' 카테고리의 다른 글
사용자의 브라우저가 표시 할 수있는 모든 글꼴 나열 (0) | 2020.09.25 |
---|---|
npm : "0.1"버전이 잘못된 이유는 무엇입니까? (0) | 2020.09.25 |
Map / Reduce 란 무엇입니까? (0) | 2020.09.25 |
PHP의`post_max_size`를 초과하는 파일을 정상적으로 처리하는 방법은 무엇입니까? (0) | 2020.09.25 |
C #에서 C ++ 코드를 호출 할 수 있습니까? (0) | 2020.09.25 |