[Django] Shopping Mall (10)
로그인 페이지 연결하기
accounts/views.py
from django.contrib import messages, auth
from django.contrib.auth.decorators import login_required
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = auth.authenticate(email=email, password=password)
if user is not None:
auth.login(request, user)
return redirect('home')
else:
messages.error(request, 'Invalid login credentials')
return redirect('login')
return render(request, 'accounts/login.html')
@login_required(login_url = 'login')
def logout(request):
auth.logout(request)
messages.success(request, 'You are logged out')
return redirect('login')
auth.authenticate
를 이용하면 유효성 검사를 쉽게 할 수 있다.- 로그인 로그아웃 참고
login_required
은 함수형 뷰에서만 사용 가능하고 클래스형 뷰에서는 사용할 수 없다. 이럴 때는LoginRequiredMixin
를 상속 받아서 하면 된다.- login_required 해당내용에 대해서도 위의 공식문서에
LoginRequiredMixin
를 포함해서 자세하게 나온다.
Activation link
accounts/views.py
from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes
from django.contrib.auth.tokens import default_token_generator
from django.core.mail import EmailMessage
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
phone_number = form.cleaned_data['phone_number']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
username = email.split("@")[0]
user = Account.objects.create_user(
first_name=first_name,
last_name=last_name,
email=email,
username=username,
password=password
)
user.phone_number = phone_number
user.save()
# USER ACTIVATION
current_site = get_current_site(request)
mail_subject = 'Please activate your account'
message = render_to_string(
'accounts/account_verification_email.html', {
"user" : user,
"domain" : current_site,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': default_token_generator.make_token(user),
})
to_email = email
send_email = EmailMessage(mail_subject, message, to=[to_email])
send_email.send()
messages.success(
request,
'We have sent you a verification email [email@gmail.com]. Please verify it.'
)
return redirect('/accounts/login/?command-verification&email='+email)
else:
form = RegistrationForm()
context = {
'form' : form,
}
return render(request, 'accounts/register.html', context)
get_current_site
-request를 보낸 site를 알려주고 이를 templates에 넘겨서 이를 통해 url에 동적으로 접근하도록 한다. -참고render_to_string
참고 -template 객체를 반환하면서 동시에 렌더링한다.- user.pk는 자연수 값이다 이를
force_bytes
를 통해 bytes로 변환해준다. 그 후urlsafe_base64_encode
를 통해 인코딩해서uid
를 만든다.- 이전에는 six를 통해 tokens.py 를 만들고 따로 상속받아서 해결했었는데 굳이 그럴 필요 없다.
default_token_generator.make_token
를 통해 토큰을 만들어준다.EmailMessage
를 이용해서 이메일을 보내준다.'/accounts/login/?command-verification&email='+email
를 통해 유저가 로그인 페이지에서 패스워드만 입력하면 되게 만든다. (email 주소는 이미 써져있음)
account_verification_email.html
{% autoescape off %}
Hi {{user.first_name}},
Please click on below link to confirm your registration.
http://{{domain}}{% url 'activate' uidb64=uid token=token %}
If you think it's not you, please ignore this email.
{% endautoescape %}
settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = MY_EMAIL
EMAIL_HOST_PASSWORD = EMAIL_PASSWORD
EMAIL_PORT = '587'
EMAIL_USE_TLS = 'True'
accounts/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('activate/<uidb64>/<token>/', views.activate, name='activate'),
]
이메일을 링크를 클릭하면 path에 있는 주소로 들어오게 된다. 그럼 views에 있는 activate를 호출하게 된다.
accounts/views.py
def activate(reqeust, uidb64, token):
# return HttpResponse('ok')
try:
uid = urlsafe_base64_decode(uidb64).decode()
user = Account._default_manager.get(pk=uid)
except(
TypeError, ValueError, OverflowError, Account.DoesNotExist
):
user = None
if user is not None and default_token_generator.check_token(
user, token
):
user.is_active = True
user.save()
messages.success(
reqeust,
'Thank you! Your account is activated.')
return redirect('login')
else:
messages.error(reqeust, 'Invalid activation link')
return redirect('register')
- 디코딩한 uid를
_default_manager
를 통해 쿼리셋으로 user 를 생성한다_default_manager
참고 ->MyAccountManager
로 커스텀 했기 때문에 `_base_manager’ 대신 사용한다- 참고
- 참고2
_base_manager
vs _default_manager
In Django, the **_default_manager**
attribute is automatically added to your model class and provides a reference to the default manager for that model. The default manager is the one defined in the model’s **Meta**
class using the **objects**
attribute.
The purpose of the **_default_manager**
is to allow easy access to the default manager for the model, even if you have defined custom managers for your model. It ensures that you always have a reference to the default manager, regardless of any customizations you have made.
Here’s a breakdown of the different manager attributes:
**_default_manager**
: This attribute provides access to the default manager for the model. It is automatically generated by Django and points to the manager specified in the **objects**
attribute of the model’s **Meta**
class.
**_base_manager**
: This attribute provides access to the base manager for the model. The base manager is the first manager defined in the model’s **Meta**
class. If you haven’t defined any custom managers, the default manager is also the base manager.
So, to answer your question about using custom managers:
**_default_manager**
is used to access the default manager, regardless of whether you have defined custom managers or not. It ensures that you can always access the default manager reliably.
**_base_manager**
is used when you want to specifically access the base manager, which could be the default manager or a custom manager if you have defined one. This can be useful if you want to bypass any customizations made in the default manager and directly access the base functionality.
user = Account._default_manager.get(pk=uid)
In the above code, **_default_manager**
is used to retrieve a user object based on the decoded **uid**
value. It provides access to the default manager of the **Account**
model, allowing you to retrieve the user using the primary key (**pk**
) value **uid**
.
Overall, **_default_manager**
and **_base_manager**
provide different ways to access the managers associated with a model, allowing you to work with the default manager or any custom managers you have defined, depending on your needs.
댓글남기기