account system - pai-plznw4me/django-initializer GitHub Wiki
κ³μ μ κ΄λ¦¬ νλ μμ€ν μ λλ€. ν΄λΉ λ³Έ λ¬Έμλ django κΈ°λ°μ κ³μ κ΄λ¦¬ μμ€ν μ λΉ λ₯΄κ² μΉ νλ‘κ·Έλ¨μ μ μ©νκΈ° μν΄ κ°λ° λμμ΅λλ€.
β οΈ ν΄λΉ λ¬Έμλ django accountμ μ¬μ©ν΄ κ°λ°μ νλκ°λ°μ
μ© λ¬Έμμ λλ€.
ν΄λΉ λ¬Έμλ₯Ό μ½κ³ django κ³μ κ΄λ¦¬ μμ€ν μ λ³ΈμΈμ΄ μ§ννκ³ μ νλ νλ‘μ νΈμμ μ©
λ°μ»€μ€ν λ§μ΄μ§
ν μ μμ΅λλ€.
git page : account
- λ€μ΄κ°κΈ° μ μ
- auth URL λ±λ‘
- νμ κ°μ μμ€ν
- Login & Logout
- Profile
- Superuser
- Admin Site
λΉ λ₯Έμ΄λ : 0. λ€μ΄κ°κΈ° μ μ | 1. auth URL λ±λ‘ | 2. νμ κ°μ μμ€ν | 3.Login & Logout | 4.Profile | 5.Superuser | 6.Admin Site
- Project μμ± ( ν΄λΉ ν¬μ€ν
μμλ
ams
) - app μμ±( ν΄λΉ ν¬μ€ν
μμλ
account
) - app λ±λ‘
- app url μμ± λ° λ±λ‘
- package install
λΉ λ₯Έμ΄λ : 0. λ€μ΄κ°κΈ° μ μ | 1. auth URL λ±λ‘ | 2. νμ κ°μ μμ€ν | 3.Login & Logout | 4.Profile | 5.Superuser | 6.Admin Site
django λ΄ κΈ°λ³Έ app μ€ νλμΈ auth app url μ λ±λ‘νλ€.
# νμΌ μμΉ
# ams
# |-account
# |-ams
# |-urls.py <-- νμΌ μμΉ
urlpatterns = [
path('admin/', admin.site.urls),
path('account', include('account.urls'), name='account'),
path('account/', include('django.contrib.auth.urls')), #<-- django auth app url μ λ±λ‘
]
- μλ² μ€νμ ν
http://127.0.0.1:8000/account/
μ€νμ μλμ κ°μ νμ΄μ§ μμ± λλ©΄ μ μ
β checkpoint
λΉ λ₯Έμ΄λ : 0. λ€μ΄κ°κΈ° μ μ | 1. auth URL λ±λ‘ | 2. νμ κ°μ μμ€ν | 3.Login & Logout | 4.Profile | 5.Superuser | 6.Admin Site
django μ€μΉμ κΈ°λ³Έ μ± κΈ°λ₯μΌλ‘ μ μ λͺ¨λΈμ μ 곡νλ€.νμ§λ§ μ μ μμ± κΈ°λ₯μ κ΄λ¦¬μ μ±μμ μ 곡λλ€. ν΄λΉ νμ΄μ§μμλ django κΈ°λ³Έ μ μ λͺ¨λΈμ νμ©ν΄ νμ κ°μ νμ΄μ§λ₯Ό λ§λ€κ³ κΈ°λ³Έ μ μ λͺ¨λΈμ νμ₯νμ¬ κΈ°μ‘΄ μ μ λͺ¨λΈμ μλ‘μ΄ νλλ₯Ό μΆκ° ν μ μλλ‘ νλ€.
-
Model
-Form
-View
-Template
ν¨ν΄μΌλ‘ κ°λ° λ¨.
- User λͺ¨λΈ μμλ°μ μλ‘μ΄ field μΆκ°νκΈ°
from django.contrib.auth.models import AbstractUser
from django.db import models
# Create your models here.
class CustomUser(AbstractUser): # <-- μμ λΆλΆ
phone_number = models.CharField(max_length=11) # μ νλ²νΈ(char)
career = models.IntegerField() # κ²½λ ₯ (int)
rank = models.CharField(max_length=10) # μ§κΈ (select)
region = models.CharField(max_length=100) # μ£Όμ
date_company_joined = models.DateField() # μ
μ¬ κΈ°κ°
id_number = models.CharField(max_length=13) # μ£Όλ―Όλ±λ‘λ²νΈ
department = models.CharField(max_length=13) # λΆμ
resume = models.FileField(blank=True, null=True) # μ΄λ ₯μ
id_photo = models.ImageField(blank=True, null=True, upload_to='') # μ¦λͺ
μ¬μ§
def __str__(self):
return self.username
-
AbstractUser μ μμλ°λ CustomUser μμλ μ AbstractUser μμ μ μλ field μ΄μΈμ μΆκ° νκ³ μΆμ field μ μ μνλ©΄ λλ€
-
AbstractUser
μλμ κ°μ fieldμ κ°μ§κ³ μλ€.-
username
-
first_name
-
last_name
-
email
-
date_joined
-
is_staff
-
-
-
β οΈ μλ‘κ² μΆκ°λλ νλμ null νμ©μ΄ μλκ±°λ νλμ κΈ°λ³Έκ°μ΄ μ€μ λμ§ μμΌλ©΄ manage.pycreatesupseruser
μΌλ‘ μνΌμ μ μμ±μ admin site μ μ κ·Όμ΄ μλ μ μλ€.
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = ('username',
'date_company_joined',
'phone_number',
'career',
'rank',
'date_company_joined',
'gender',
'id_number',
'department',
'resume',
'id_photo',
'password1',
'password2') # <- User μμ±μ 보μ¬μ€ field μ μ μνλ€.
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# null=Trueλ‘ μ€μ ν νλμ λν΄ requiredλ₯Ό Falseλ‘ μ€μ
self.fields['resume'].required = False
self.fields['id_photo'].required = False
-
UserCreationForm
μ μμ κ΄κ³λ μλμ κ°λ€.forms.ModelForm
βBaseUserCreationForm
βUserCreationForm
ModelForm
μ΄ λΆλͺ¨ ν΄λμ€μ΄λ€.ModelForm
μ¬μ© λ°©λ²λλ‘UserCreateForm
μ μ¬μ©νλ©΄ λλ€. - image field μ μ¬μ©ν λ €λ©΄ Pillow package κ° νμνλ€.
pip install Pillow
- settings.py μ λͺ¨λΈ λ±λ‘
# settings.py
AUTH_USER_MODEL = 'account.CustomUser'
- python manage.py makemigrations
- python manage.py migrates
-
ν΄λ μμ±
mkdir -p account/templates/account
-
templates μμ±
touch account/templates/account/signup.html
<!-- templates/registration/login.html --> <h2>Signup</h2> <form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} {{ form.as_p }} <button type="submit">Signup</button> </form> {{ errors }}
-
νμκ°μ
def signup(request): if request.method == 'POST': form = CustomUserCreationForm(request.POST, request.FILES) # <-- FILES μ κ°μ΄ μ λ ₯μ΄ λμ΄μΌ νλ€. if form.is_valid(): # file field λ°μ΄ν° μ μ₯ inst = form.save(commit=False) # file field λ°μ΄ν° μ μ₯ id_photo = form.cleaned_data['id_photo'] inst.id_photo.save(id_photo.name, id_photo) # Signup κ²°κ³Ό νμ΄μ§ return HttpResponse('Signup complete') else: print('Errors:', form.errors) return render(request, template_name='account/signup.html', context={'errors': form.errors}) elif request.method == 'GET': form = CustomUserCreationForm() # <-λ°λ λΆλΆ return render(request, template_name='account/signup.html', context={'form': form}) else: raise NotImplementedError
-
account URLConf λ±λ‘
# ams/account/urls.py from django.urls import path, include from account.views import signup app_name = 'account' urlpatterns = [ path('signup/', signup, name='signup') ]
β Checkpoint
# settings.py
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'
# ams/urls.py
from django.conf.urls.static import static
from ams import settings
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
λΉ λ₯Έμ΄λ : 0. λ€μ΄κ°κΈ° μ μ | 1. auth URL λ±λ‘ | 2. νμ κ°μ μμ€ν | 3.Login & Logout | 4.Profile | 5.Superuser | 6.Admin Site
- LoginView class λ‘ μ΄λ ν μλ μ½λλ‘ λ³κ²½
LoginView λ ν΄λΉ μμΉμ μ μλμ΄ μλ€. (
django.contrib.auth.views import LoginView
)
# django.contrib.auth.views import LoginView <-- μ¬κΈ°λ‘ μ΄λν λ³κ²½
class LoginView(RedirectURLMixin, FormView):
...
template_name = "account/login.html" # <-- βοΈ μ¬κΈ° λΆλΆμ λ³κ²½νλ€.
...
touch account/templates/account/login.html
<!-- templates/account/login.html -->
<h2>Log In</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Log In</button>
</form>
β Checkpoint (3.1, 3.2)
(accounts/profile/
κ²½λ‘λ‘ redirect νλ€.)
- λ‘κ·ΈμΈ μ΄ν κ°κ³ μ νλ url μ settings.py μ λ±λ‘
- μλ μμμμλ account/profile λ‘ λ‘κ·ΈμΈ μ΄ν redicrect νλλ‘ λ³κ²½ (4. Profile μμ μΆκ° μ ν μ§ν μμ )
# settings.py
LOGIN_REDIRECT_URL = '/account/profile'
1.1 auth app λ±λ‘
λ¨κ³λ₯Ό μ§ννλ€λ©΄ λ¨μν /accounts/logout
url λ‘ μ μνλ©΄ λλ€.
λ‘κ·ΈμΈ νμ΄μ§μ κ°κ² settings.py
μ logout μ±κ³΅ μ μ΄λνλ νμ΄μ§λ₯Ό μ μν΄ λλ€.
LOGOUT_REDIRECT_URL = 'home' # new
λΉ λ₯Έμ΄λ : 0. λ€μ΄κ°κΈ° μ μ | 1. auth URL λ±λ‘ | 2. νμ κ°μ μμ€ν | 3.Login & Logout | 4.Profile | 5.Superuser | 6.Admin Site
- templatetags μμ±
mkdir -p account/templatetags
touch account/templatetags/index.py
# account/templatetags/index.py
from django import template
register = template.Library()
@register.filter
def index(indexable, i):
return indexable[i]
@register.filter
def getattribute(indexable, attr):
return indexable.__getattribute__(attr)
- template profile.html μμ±
touch account/templates/account/profile.html
<!-- account/templates/account/profile.html -->
{% load index %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for field in field_names %}
{% with field_type=types|index:forloop.counter0 attr=user|getattribute:field %}
{% if field_type == 'ImageField' %}
{{ field }} : <p><img src={{ attr|getattribute:'url' }}></p>
{% elif field_type == 'FileField' %}
{{ field }} : <p><a href={{ attr|getattribute:'url' }}>{{ attr }}</a></p>
{% else %}
<p>{{ field }} : {{ attr }} : {{ types | index:forloop.counter0 }}</p>
{% endif %}
{% endwith %}
{% endfor %}
</body>
</html>
# κ²½λ‘ : ams/account/forms.py
class CustomUserProfileForm(UserCreationForm):
class Meta:
model = CustomUser
# νμ κ°μ
νμ΄μ§μμ 보μ¬μ€ κΈ°λ³Έ μ μ νλ
base_field = ['username',
'first_name',
'last_name',
'email']
# νμ κ°μ
νμ΄μ§μμ 보μ¬μ€ 컀μ€ν
μ μ νλ
custom_field = ['phone_number',
'career',
'rank',
'date_company_joined',
'id_number',
'department',
'resume',
'id_photo',
'region']
fields = tuple(base_field + custom_field)
from django.db import models
@csrf_exempt
def profile(request):
user = CustomUser.objects.get(username=request.user)
# field μ΄λ¦μ μΆμΆν©λλ€.
field_names = CustomUserProfileForm.Meta.field
# field λ³ type μ μΆμΆν©λλ€.
types = []
for name in field_names:
field = user._meta.get_field(name)
# field κ° Image type μ΄λ©΄ 'ImageType' μΌλ‘ νμ
μ μ μ₯ν©λλ€.
# λͺ¨λΈ νλμ λ΄λΆ νμ
μ μ€μ λ°μ΄ν°λ² μ΄μ€μμ μ¬μ©λλ νμ
μ
λλ€.
# get_internal_type()μΌλ‘ λ°νλλ κ°μ FileField μ
λλ€.
if isinstance(field, models.ImageField):
types.append('ImageField')
else:
types.append(field.get_internal_type())
# template μ rendering ν©λλ€.
context = {'user': user, 'field_names': field_names, 'types':types}
return render(request, template_name='account/profile.html', context=context)
# ams/account/urls.py
app_name = 'account'
urlpatterns = [
path('signup/', signup, name='signup'),
path('profile/', profile, name='profile'),
]
β
Checkpoint (4.Profile)
λΉ λ₯Έμ΄λ : 0. λ€μ΄κ°κΈ° μ μ | 1. auth URL λ±λ‘ | 2. νμ κ°μ μμ€ν | 3.Login & Logout | 4.Profile | 5.Superuser | 6.Admin Site
-
helper.py νμΌ μμ±
touch ams/account/helper.py
# touch ams/account/helper.py μ μλ μ½λ μμ± from account.models import CustomUser def createsuperuser(): CustomUser.objects.create_superuser(username='admin', email='[email protected]', password='q1w2e3r4Q!W@E#R$', first_name='admin', last_name='admin', phone_number='01062766596', career=2, rank='manager', date_company_joined='2022-02-02', id_number='admin', department='κ΄λ¦¬λΆ', region='μμΈ').save() return 'Create Superuser : admin ' if __name__ == '__main__': createsuperuser()
-
helper νμΌ μ€ν
python manage.py shell
from account.helper import createsuperuser createsuperuser()
β
terminal μ μλ λͺ
λ Ήμ΄ λ³΄μΌμ μ±κ³΅
'Create Superuser : admin '
λΉ λ₯Έμ΄λ : 0. λ€μ΄κ°κΈ° μ μ | 1. auth URL λ±λ‘ | 2. νμ κ°μ μμ€ν | 3.Login & Logout | 4.Profile | 5.Superuser | 6.Admin Site
- ams/account/admin.py μ μλ μ½λ μΆκ°
- profile page μμ 보μ΄λ μ μ μμ±μ λͺ¨λ νμΈ ν μ μμ
from django.contrib import admin
# Register your models here.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from account.forms import CustomUserProfileForm
from account.models import CustomUser
class CustomUserAdmin(UserAdmin):
model = CustomUser
list_display = CustomUserProfileForm.Meta.fields
admin.site.register(CustomUser, CustomUserAdmin)
β Checkpoint