Django에서는 아래와 같이 꼭 입력을 받아야하는 CharField에 대해 null=True 조건을 주지 않고 생성합니다.
(not null 이 default)
models.py
class CharTest(models.Model):
a = models.CharField(max_length=10)
b = models.CharField(max_length=10)
그런데 null=True를 주지 않은
not null 상태인데 값을 안받고 DB에 데이터가 생기는 경우가 있습니다.
어떤 경우인지 살펴보도록 하겠습니다.
아래와 같이 POST 요청으로 a를 받아서 object를 생성해보겠습니다.
test.html
<form action="/test" method="POST">
{% csrf_token %}
<div><input type="text" name="a" placeholder="a"></div>
<button>send</button>
</form>
아래와 같이 하고 123을 입력해서 POST 요청을 해보겠습니다.
views.py
def not_null_test(request):
if request.method == 'GET':
return render(request, 'test.html')
elif request.method == 'POST':
data = request.POST
print(data.get("a"))
print(data.get("b"))
CharTest.objects.create(
a = data.get("a"),
b = data.get("b")
)
return JsonResponse(data)
b값을 html에서 넘겨주고 있지 않으니 data.get("b") 는 None이 될것입니다.
그리고 ChatTest table에 row data를 생성하려고 시도하지만 b 가 not null 이므로 아래와 같이 에러가 발생합니다.
그럼 다음과 같이 ChatTest object를 생성하면 어떻게 될까요?
views.py
def not_null_test(request):
if request.method == 'GET':
return render(request, 'test.html')
elif request.method == 'POST':
data = request.POST
print("a: ", data.get("a"))
print("b: ", data.get("b"))
CharTest.objects.create(
a = data.get("a")
)
return JsonResponse(data)
b값 자체를 받지 않고서 object를 생성하는 것입니다.
CharTest table을 models.py에서 정의해주면서 null=True 옵션을 주지 않은 것은
CharTest table에 row 데이터가 생성될 때 반드시 a, b field 모두 값을 받을 때만 생성되도록 의도했을 것입니다.
그럼 위와 같은 POST 요청에도 ChatTest에 row data가 생성되지 않을 것을 기대했을 것입니다.
그럼 기대대로 될지 똑같이 a=123을 넣어서 생성해주겠습니다.
위와 같이 에러 없이 데이터가 생성되었습니다.
그럼 b는 어떻게 저장이 될까요? null로? 이때 b에는 null 이 아닌 빈 값 자체가 DB에 저장되게 됩니다.
모델을 설계할 때, b값이 안들어오면 생성이 되지 않는 것을 기대했을 것입니다.
따라서 위와 같은 불상사가 생기지 않도록 하기 위해서는 MODEL.objects.create()를 이용할 때 반드시 not null field는 값을 입력 받아서 생성해주도록 하고 (값이 없을 때는 None이 들어오도록)
이게 아니면 적어도 front단이나 Back단에서 생성 전에 예외 처리를 해주도록 해야 합니다.
이런 문제는
.objects.create(a=a, b=b, ...)와 같이 개별적으로 field에 들어갈 값들을 지정하는 경우에는 실수를 할 일이 잘 없습니다.
그런데 아래와 같이 request로 들어오는 데이터를 unpack해서 생성할 때는(**data) 원하지 않는 결과가 생길수 있습니다.
input에 321 값을 넣어서 POST 요청을 해보겠습니다.
views.py
def not_null_test(request):
if request.method == 'GET':
return render(request, 'test.html')
elif request.method == 'POST':
data = request.POST
data = {k:v for k,v in data.items() if k != 'csrfmiddlewaretoken'}
print(data)
CharTest.objects.create(**data)
return JsonResponse(data)
위의 예에서 보면 data가 unpack 되면서 a=321 만 받아서 생성되게 되고, b는 값을 받아서 생성하는 옵션 자체가 안들어가게 됩니다. 그럼 아래와 같이 b가 not null field임에도 DB에 row data가 생성되게 됩니다.
요약
* not null field는 반드시 object 생성시 값을 지정해서 생성
* unpack으로 생성할때는 not null field가 값이 없는 상태로 Table row data가 생성되지 않도록 예외처리 필수
'Python > Django' 카테고리의 다른 글
Django DateField, HTML input type date (0) | 2023.02.22 |
---|---|
Django admin: Register all models # Django admin page에 모든 모델 등록 (0) | 2023.02.19 |
Django app 위치 변경 # + 생성 (0) | 2023.02.06 |
Django ORM Query: ForeignKey로 연결된 필드 filter (0) | 2023.02.04 |
Django Template, render_to_string # backend에서 data 받기 #render_to_string #loader (0) | 2023.01.29 |