본문 바로가기

TIL

23.04.07 TIL

오늘 한 것

오늘 TIL은 개인과제를 마무리하는 과정에서 마주한 에러들과 문제, 의문들을 정리하고자 한다.

0. ERD 그리기

데이터 베이스의 필드와 구조의 변경이 있어 반영하여 새로 ERD를 그렸다.

DBdiagram.io

Link for DBdiagram.io

ERDcloud

1. django: auto_now_add Vs. auto_now

DateField는 auto_now와 auto_now_add 매개변수를 받을 수 있다. 이 둘이 무슨 차이인지 궁금했다.

해결: 공식 문서

DateField.auto_now
Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps.

auto_now는 객체가 새로 save 메소드를 실행해 업데이트 될 때마다 값을 업데이트 한다. 즉, 가장 최근에 수정된 시간/날짜를 저장하게 된다.

DateField.auto_now_add
Automatically set the field to now when the object is first created. Useful for creation of timestamps.

auto_now_add는 객체가 생성 될 때 저장한다. 즉, 처음 생성된 시간을 저장하게 된다. 이 둘과 default 옵션은 서로 상호배타적이며, 셋 중 둘 이상을 같이 쓰려고 하면 에러를 발생시킨다.

2. 어드민 페이지에서 보이지 않는 테이블

makemigrations와 migrate를 정상적으로 실행했음에도 어드민 페이지에서 보이지 않는 테이블들이 있었다.

 

해결: admin.py

from django.contrib import admin
from erp.models import ProductModel, InBound, OutBound, Inventory
# Register your models here.
admin.site.register(ProductModel)
admin.site.register(InBound)
admin.site.register(OutBound)
admin.site.register(Inventory)

해당 모델이 만들어진 app의 admin.py에 위와같이 모델을 등록시켜 주면 볼 수 있다.

3. .gitignore의 한계

다른 동기들과 함께 깃헙에 push하던 도중, 일부 인원에게서 데이터베이스 파일이 깃헙에 올라가 보안 경고 메일이 오거나, DB접근을 위한 시크릿 키가 그대로 공개되어 문제가 발생할 여지가 생기는 경우가 있었다.

시도 1. gitignore 사용

이를 막기 위해 .gitignore를 뒤늦게 사용하였으나, 이미 커밋 히스토리 에서는 그대로 민감한 내용이 노출되어 있었다. 나도 마찬가지였다.

해?결

이를 해결하기 위해서는 그냥 .git을 지우고, 다시 git init을 하는 것 밖에 할 수 있는게 없었다. 커밋 히스토리를 아깝지 않게 하기 위해서는 앞으로는 .gitignore를 작성할 때는 처음부터 작성해 두어야한다. 이를 도와주는 웹사이트도 이미 존재하므로 적극 이용하자... 이번엔 커밋 수가 많지 않아서 다행이지만 앞으로 이런 속 쓰린 일이 두번다시 있으면 안될 것이다...

???: 아아 네 커밋들 말인가??
???: 이걸 말하는 건가wwww

킷사마ㅏㅏㅏㅏㅏ!!!!

 

4. OperationalError, no such column

모델을 변경 하고 migrate까지 끝낸 뒤 서버에 접속하려 하자, 위와 같은 오류가 뜨면서 일부 모델이 사용되는 몇 페이지가 접속이 되지 않았다. 이는 기존 모델에 없던 필드를 추가했기 때문에 오류가 발생한 것이었다.

 

시도 1. 어드민 페이지 접속해서 삭제

어드민 페이지 조차 오류를 발생시키며 접속이 되지 않았다.

 

시도 2. DB 삭제

결국 DB 전체를 삭제하는 식으로 해결 하였다. 그러나 이는 근본적인 해결방법이라고 볼 수 없다. 따라서 장고에서 제공하는 기능을 사용하여 이런 오류가 발생하는 것을 막을 수 있는지 찾아보기로 했다.

해결

1. 새 필드에 기본값을 설정해준다.

class MyModel(models.Model):
    new_field = models.CharField(max_length=100, default='default value')

이렇게 기본값을 설정해줄 경우, 기존에 이 필드를 가지지 않았던 데이터들은 자동으로 해당 필드를 기본값으로 채운다.

 

2. 새 필드에 null값을 허용한다.

class MyModel(models.Model):
    new_field = models.CharField(max_length=100, null=True)

3. makemigrations의 옵션을 사용해 기본값 지정하기

python manage.py makemigrations <app> --name <field> --add-field <model>.<field> --default 'default value'
python manage.py migrate

기본값 설정업이 이미 필드를 추가했다면 위와같은 옵션을 사용해 메이크마이그레이션을 해서 해결할 수 있다.

 

5. 값 범위 제한 

수량, 가격 등 음수가 될 수 없는 필드의 값을 0 이상으로 제한 하고 싶었다.

 

시도 1. views.py에서 직접 걸러내기

cleaned_data를 통해 폼으로부터 데이터를 가져와 값이 원하는 범위안에 있는지 확인한다.

def inbound(request):
    if request.method == 'POST':
        inbound_form = InBoundForm(request.POST)
        if inbound_form.is_valid():
        	if inbound_form.cleaned_data['amount']<0:
            	return redirect('/')
            if inbound_form.cleaned_data['cost']<0:
            	return redirect('/')
            inbound_form.save()
            return redirect('/')
        return redirect('/product/')

해결은 되지만 범위가 필요한 각 필드마다 if문을 작성해야하므로 코드가 간결하지 못하다.

 

시도 2. form.is_valid() 오버라이딩

모델form의 입력값이 유효한지 검사하는 is_valid() 메서드를 오버라이딩 하여 범위 안에 있는지 확인하는 기능을 추가한다.

class InBoundForm(forms.ModelForm):
    class Meta:
        model = InBound
        fields = ['amount', 'cost', 'code_name_size']
    def is_valid(self):
    	if not super().is_valid():
        	return False
        return bool(self.cleaned_data['amount']>=0 and self.cleaned_data['cost']>=0)

이것도 폼에 우겨넣어서 views.py에선 안보일 뿐 시도 1과 유사한 문제가 있다. 또한 장고가 기본적으로 제공하는 기능을 통해 원하는 것을구현할 수 있을 것 같았다.

 

해결. validator 활용

장고는 기본적으로 필드에 들어온 값의 유효성을 판별하는 기준을 정해주는 validator들을 제공한다.

from django.core.validators import MinValueValidator  # 벨리데이터 임포트

class InBound(models.Model):
    """
    입고 모델입니다.
    상품코드, 수량, 날짜, 금액 필드를 가집니다.
    """
    class Meta:
        db_table = 'inbound'
    code_name_size = models.ForeignKey(Inventory, on_delete=models.CASCADE,)
    inbound_date = models.DateField(auto_now_add=True)
    cost = models.IntegerField(validators=[MinValueValidator(0)])  # 필드에 적용
    amount = models.IntegerField(validators=[MinValueValidator(0)])

이렇게 하면 각 필드마다 간편하게 범위 제한을 걸 수 있다.

 

오늘 배운 것

1. 장고의 모델 폼을 사용하는 몇가지 방법을 알게 되었다.

2. 깃 이그노어는 프로젝트를 시작하기 직전에 추가해야함을 알게됐다.

3. 모델 필드에 벨리데이터를 사용해 유효한 입력값의 범위를 지정할 수 있음을 배웠다.

4. auto_now, auto_now_add의 차이에 대해 배웠다.

5. 새 필드를 추가할 때는 디폴트값을 지정해 에러 발생을 막을 수 있다.

 

레퍼런스

장고 공식 문서 : validators

 

Django

The web framework for perfectionists with deadlines.

docs.djangoproject.com

장고 공식문서

 

Django

The web framework for perfectionists with deadlines.

docs.djangoproject.com

https://0ver-grow.tistory.com/949

 

 

[문제해결] django.db.utils.OperationalError: no such column: blogapp_blog.title // Y

에러django.db.utils.OpertationalError : no such columnYou are trying to add a non-nullable field 'title' to blog without a default 상황객체를 수정할 때, 중복되는 title 변수를 재수정한 후python manage.py migrations를 입력하니다

0ver-grow.tistory.com

 

 

[문제해결] django.db.utils.OperationalError: no such column: blogapp_blog.title // Y

에러django.db.utils.OpertationalError : no such columnYou are trying to add a non-nullable field 'title' to blog without a default 상황객체를 수정할 때, 중복되는 title 변수를 재수정한 후python manage.py migrations를 입력하니다

0ver-grow.tistory.com

 

 

'TIL' 카테고리의 다른 글

23.04.11 TIL(팀플개발일지)  (0) 2023.04.12
23.04.10 TIL(팀플 개발일지)  (2) 2023.04.11
23.04.06 TIL  (0) 2023.04.07
23.04.05 TIL  (0) 2023.04.05
23.04.04 TIL  (0) 2023.04.05