데이터 모델 작성 시, 자주 사용하는 필드 옵션인 null과 blank의 차이점을 제대로 이해하고 있지 않은 것 같아 정리해보기로 하였다.
+ 추가
blank = True
null = False
default = "어떤 값"
default를 초기값이라고만 생각했었는데, default를 de와 fault 로 나눠서 생각해보면 실패(오류)를 제거하다, 없애다라고 보면
blank는 입력 시 유효성 검사와 관련되어 있을 뿐, DB와는 관련이 없다. 즉, null=False라면 빈값이 들어가지 못하므로, 실패를 없애기 위한 값으로 default로 정한 "어떤 값"이 들어가게 된다.
Field.null
DB와 관련된 옵션으로 데이터가 없다는 의미를 가진다.
Django에서 CharField, TextField와 같은 문자열 기반 필드에서는 데이터가 없다는 의미를 2가지로 표현할 수 있기 때문에, NULL이 아닌 빈 문자열을 사용하는 것을 권장하고 있다.
즉, Field.null은 문자열 기반 필드에서 단독으로 사용하는 것을 권하지 않는다.
Field.blank
유효성 검사와 관련된 옵션으로 데이터가 없다는 의미를 가진다.
데이터 저장보다는 사용자 입력과 관련되어 있다고 생각하면 된다.
blank=True로 설정할 경우, 빈 값을 입력을 허용하기 때문에 유효성 검사에서 문제가 발생하지 않는다.
문자열 기반 필드에서 Field.null=True 설정을 사용해야만 하는 경우❗️
필드 옵션을 unique=True, blank=True로 설정했을 때.
💡 unique=True 설정은 해당 필드의 값이 중복되지 않는다는 의미를 갖고 있다.
직접 확인해보기
1. models.py에 예시 모델 작성
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Post(models.Model):
writer = models.ForeignKey(
User,
verbose_name="작성자",
db_column="Writer",
on_delete=models.CASCADE,
)
content = models.CharField(
verbose_name="내용",
db_column="Content",
max_length=500
)
# 이 필드 주목 #
email = models.EmailField(
verbose_name="이메일",
db_column="EMAIL",
unique=True,
blank=True,
max_length=100
)
User모델은 Django에서 제공해주는 모델을 사용하였고,
Post에는 작성자인 User를 외래키로 갖는 user 필드와 내용을 입력할 수 있는 content 필드, 이메일을 입력하는 email 필드를 갖도록 작성하였다. 그리고 email 필드 옵션에 unique=True, blank=True를 설정해주었다.
💡 unique=True, blank=True
이 때, 어떤 문제가 발생하는지 쉘을 통해 직접 확인해보자.
모델 변경 후, makemigrations와 migrate를 잊지말자!
python manage.py makemigrations
python manage.py migrate
2. python shell 접속
python manage.py shell
3. User, Post 객체 불러오기
from 앱명.models import User, Post
# 모든 모델을 한 번에 불러올 경우,
# from 앱명.model import *
4. User 객체 생성 및 저장
user1, user2 라는 이름을 가진 User객체를 각각 생성한다.
User.objects.create(username='user1', password='1234')
User.objects.create(username='user2', password='1234')
# 모든 User 객체 조회
User.objects.all()
그리고, 생성한 객체를 각각 user1, user2라는 이름으로 저장한다.
# User 객체 중 가장 첫 번째 객체를 가져올 경우, first() 사용 가능
user1 = User.objects.first()
# 그렇지 않은 경우, get() 혹은 filter() 사용
user2 = User.objects.get(username='user2')
만일 user1을 저장하지 않고, Post객체에 바로 사용하려고 한다면, 아래와 같이 user1은 정의되어 있지 않다는 에러메시지를 보게 된다.
5. Post 객체 생성_01
Post.objects.create(writer=user1, content='content01')
의도적으로 email 값을 넣지 않고 Post객체를 생성했다.
생성 후, Post.objects.values()로 확인해보면 email=''로 값이 저장됐음을 알 수 있다.
6. Post 객체 생성_02
Post.objects.create(writer=user2, content='content02')
될까? NO! 안 된다.
중요하니까 사진을 키워보자!
blank=True로 빈값을 입력받는 건 허용했으나, 이미 첫 번째로 생성한 Post 객체(writer=user1인 Post)에서 email=''로 저장했기 때문에, 이메일 필드는 해당 값이 중복을 허용하지 않는 Unique=True로 인해 에러가 발생하는 된 것이다.
👩🏻💻 그럼, Field.null=True만 해주면 되겠네!
7. Field.null=True 필드 옵션 추가
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Post(models.Model):
writer = models.ForeignKey(
User,
verbose_name="작성자",
db_column="Writer",
on_delete=models.CASCADE,
)
content = models.CharField(
verbose_name="내용",
db_column="Content",
max_length=500
)
# 이 필드 주목 #
email = models.EmailField(
verbose_name="이메일",
db_column="EMAIL",
unique=True,
blank=True,
null=True, # <--------------이 부분 추가
max_length=100
)
8. 다시 Post객체 생성
👩🏻💻 makemigrations, migrate 잊지 말기!
안 된다.
9. 해결방법
def clean(self):
if self.email == "":
self.email = None
Post모델에 함수 clean() 을 작성하여 값이 비어있을 경우, None으로 변경하여 저장할 수 있도록 한다.
💡 null? None?
python에서 null 객체는 None 으로 표현
이 글은 https://docs.djangoproject.com/en/4.0/ref/models/fields/ 참고하여 작성하였습니다.
'프레임워크(Framework) > Django' 카테고리의 다른 글
[Django] settings 파일 분리하기 (0) | 2022.09.24 |
---|---|
[Django] on_delete 옵션 (0) | 2022.09.20 |
[Django] Django 설치 및 프로젝트 생성 (0) | 2022.09.20 |
[Django|Postgre]postgreSQL설치 및 연동 (0) | 2021.12.06 |
[Django] 프로젝트와 앱 생성하기(+가상환경) ref.DjangoGirls (0) | 2021.11.19 |