python manage.py startapp account -> account 폴더 생김# account/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# User 모델 등록
## AbstractUser를 상속 받아서 확장 User 모델로 정의
class User(AbstractUser):
# username/password(AbstractUser)를 제외한 나머지 Field들을 정의
name = models.CharField(
verbose_name="이름", # Form 관련 설정. ModelForm을 만들 경우 form 관련 설정을 Model field에 할 수 있다.
max_length=50 # varchar(50)
)
email = models.EmailField(verbose_name="Email", max_length=100)
# varchar(100) -> 검증기능이 추가: 값이 이메일 형식(@를 포함하는지)인지 여부를 검증
birthday = models.DateField(
verbose_name="생일",
null=True, # nullable # default: not null
blank=True, # 입력폼 설정 - 빈값입력 가능 여부(default: False - required) # null=True와 같이 준다.
)
def __str__(self):
return f"{self.username} - {self.name}"
# python manage.py makemigrations
# python manage.py migrate
오류 원인: InconsistentMigrationHistory
오류 메시지의 핵심은 다음과 같습니다:
Migration admin.0001_initial is applied before its dependency account.0001_initial on database 'default'.
의미: Django의 admin 앱의 초기 마이그레이션(admin.0001_initial)이 account.0001_initial보다 먼저 적용되어 있다는 뜻입니다.
그런데 admin.0001_initial은 account.0001_initial에 의존성(Dependency)이 있어서, 반드시 account 마이그레이션이 먼저 적용되어야 합니다.
마이그레이션 순서가 꼬여서 Django가 데이터베이스 상태를 일관성 있게 유지할 수 없다고 판단한 것입니다.
➡️ 마이그레이션 순서를 되돌리는 방법을 제시
마이그레이션을 다시 하고 super user를 create 해야하는지 몰라서 헤맸다. ㅠㅠ
# account/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# User 모델 등록
## AbstractUser를 상속 받아서 확장 User 모델로 정의
class User(AbstractUser):
# username/password(AbstractUser)를 제외한 나머지 Field들을 정의
name = models.CharField(
verbose_name="이름", # Form 관련 설정. ModelForm을 만들 경우 form 관련 설정을 Model field에 할 수 있다.
max_length=50 # varchar(50)
)
email = models.EmailField(verbose_name="Email", max_length=100)
# varchar(100) -> 검증기능이 추가: 값이 이메일 형식(@를 포함하는지)인지 여부를 검증
birthday = models.DateField(
verbose_name="생일",
null=True, # nullable # default: not null
blank=True, # 입력폼 설정 - 빈값입력 가능 여부(default: False - required) # null=True와 같이 준다.
)
def __str__(self):
return f"{self.username} - {self.name}"
# settings.py에 사용자 정의 User 모델 등록
# database 삭제 (db.sqlite3 파일)
# python manage.py makemigrations
# python manage.py migrate
# account/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
# 관리자(admin)에서 User를 어떻게 관리할지 화면을 재구성.
# UserAdmin을 정의
## list_display: admin의 Users(사용자들)의 메인 화면 목록에 나올 항목 등록
## add_fieldsets: Tuple - User 등록 화면에 나올 항목들 지정.
## fieldsets: Tuple - User 수정 화면에 나올 항목들 지정.
class CustomUserAdmin(UserAdmin):
list_display = ["username", "name", "email"]
add_fieldsets = (
("인증정보", {"fields":("username", "password1", "password2")}),
("개인정보", {"fields":("name", "email", "birthday")})
)
fieldsets = (
("인증정보", {"fields":("username", "password")}),
("개인정보", {"fields":("name", "email", "birthday")})
)
admin.site.register(User, CustomUserAdmin)

사용자들 버튼 클릭

사용자 추가 + 버튼을 누르면

인증정보 -> 사용자 이름, 비밀번호, 비밀번호 확인
개인정보 -> 이름, 이메일, 생일
# account/forms.py
## Form이나 ModelForm 클래스들을 정의하는 모듈
## 보통 Form은 등록/수정 폼 각각 하나씩 정의.
## User 등록 폼, User 수정 폼 ==> ModelForm
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import User
# ModelForm: ModelForm을 상속, Form: forms.Form을 상속
# UserCreationForm에 정의된 Form필드: username, password1, password2
# CustomUserCreationFrom: UserCreationForm의 form필드 + name, email, birthday
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = User # User Model의 model field를 이용해서 Form field를 구성.
fields = "__all__" # 모델의 모든 field들을 이용해서 구성.
# fields = ["name", "email"] # 특정 model field들을 선택해서 구성.
# exclude = ["name"] # 지정한 model field를 제외한 나머지를 이용해서 구성. (fields와 exclude는 같이 사용 못한다.)
# \config\urls.py
urlpatterns = [
path("", TemplateView.as_view(template_name="home.html"), name="home"),
path('admin/', admin.site.urls),
# path('polls/welcome', views.welcome_poll, name="welcome"),
path("polls/", include('polls.urls')),
path("account/", include("account.urls")),
]
먼저 기본 틀을 잡는다.
# account/urls.py
from django.urls import path
from . import views
app_name="account"
urlpatterns = [
]
urlpatterns에 path를 지정해준다.
이때 변수명을 urlpatterns라고 꼭 해줘야 한다. url_patterns라고 적었다가 오류남 ㅠㅠ
# account/urls.py
from django.urls import path
from . import views
app_name="account"
urlpatterns = [
path("create", views.create, name="create"),
]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls',
'account',
'django_bootstrap5', # ⭐ 여기
]
# account/views.py
from django.shortcuts import render
from .forms import CustomUserCreationForm
#########################
# 사용자 가입 처리
# 요청 url: account/create
# 가입이나 수정은 항상 두 단계로 나뉜다.
# GET - 가입 폼 양식을 응답
# POST - 가입 처리
# view 함수: create
# 응답: GET - templates/account.create.html
# POST - home으로 이동. redirect 방식으로 (새로고침해도 votes 추가 되지 않게 하기 위해서)
def create(request):
if request.method == "GET":
return render(request, "account/create.html", {"form":CustomUserCreationForm()})
else: # POST
pass
<!-- account/templates/account/create.html -->
{% extends "layouts/main_layout.html" %}
{% load django_bootstrap5 %}
{% comment %}
django_bootstrap5 사용. django template에서 bootstrap을 적용할 수 있는 태그들을 제공하는 lib.
`pip install django_bootstrap5`
form 입력에 bootstrap을 적용
settings.py에 앱 등록
{% endcomment %}
{% block title %}회원가입{% endblock title %}
{% block contents %}
<h1>회원가입</h1>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<div class="mt3">
<button type="submit" class="btn btn-primary">가입</button>
<button type="reset" class="btn btn-primary">초기화</button>
</div>
</form>
{% endblock contents %}
<a href="{% url 'account:create' %} class=nav-link"></a>