본문 바로가기

Python/Django

[Django] DB - Update, Delete

이번에는 데이터베이스에서 CRUD 중 업데이트, 삭제에 대해서 알아보겠습니다.

먼저, 업데이트 모델과 업데이트 엔트리에 대해서 알아보겠습니다.

 

 

 

  • 모델 업데이트에 대해서 알아보겠습니다. 기존 테이블에 새로운 컬럼을 기본값없이 추가해보겠습니다.
from django.db import models
from django.core.validators import MaxValueValidator,MinValueValidator

# Create your models here.
class Patient(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30) 
    age = models.IntegerField(validators=[MinValueValidator(0),MaxValueValidator(120)]) 
    # 추가된 코드, 기본값설정이 없는 경우
    heartrate = models.IntegerField()

    def __str__(self):
        return f"{self.last_name}, {self.first_name} is {self.age} years old."

 

새 컬럼, 즉 모델 클래스의 속성을 추가할 때, 기존 데이터에는 null 값 또는 디폴트 값을 삽입해야 한다.
새로운 컬럼의 기본 값을 설정하지 않고 마이그레이션을 실행할면, Django는 아래와 같은 옵션을 제시한다.

 

(django) ~\my_site>python manage.py makemigrations office
It is impossible to add a non-nullable field 'heartrate' to patient without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit and manually define a default value in models.py.
Select an option: 2

(django) ~\my_site>

 

2가지 옵션의 의미는

1) 마이그레이션 파일을 생성할 때, 기본값을 선택, 기존 모든 데이터의 새로운 컬럼에 대한 값을 설정

2) 마이그레이션 파일을 생성을 취소하고, 모델(models.py) 내에서 디폴트 값을 생성하도록 안내한다.

 

 

일반적으론 두번째 경우인, 디폴트 값을 models.py 내에 정의하는것이 좋다. 아래 추가된 코드 참고

 

from django.db import models
from django.core.validators import MaxValueValidator,MinValueValidator

# Create your models here.
class Patient(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30) 
    age = models.IntegerField(validators=[MinValueValidator(0),MaxValueValidator(120)]) 
    # 추가된 코드, 기본값을 설정한 경우
    heartrate = models.IntegerField(default=60,validators=[MinValueValidator(1),MaxValueValidator(300)])

    def __str__(self):
        return f"{self.last_name}, {self.first_name} is {self.age} years old."

 

 

새로운 마이그레이션 파일이 생성되었다.

 

(django) ~\my_site>python manage.py makemigrations office
Migrations for 'office':
  office\migrations\0002_patient_heartrate.py
    - Add field heartrate to patient

(django) ~\my_site>
(django) ~\my_site>
(django) ~\my_site>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, office, sessions
Running migrations:
  Applying office.0002_patient_heartrate... OK

(django) ~\my_site>

 

 

결과화면 - 새로운 행에 기본값이 추가된 것을 볼 수 있다

 

 

 

  • 엔트리 업데이트에 대해서 알아보겠습니다.
(django) ~\my_site>python manage.py shell
Python 3.10.4 | packaged by conda-forge | (main, Mar 30 2022, 08:38:02) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 
>>> from office.models import Patient
>>> Patient.objects.get(pk=1)
<Patient: smith, carl is 30 years old.>
>>> 
>>> carl = Patient.objects.get(pk=1)
>>> print(carl)
smith, carl is 30 years old.
>>> carl.last_name
'smith'
>>> 
>>> carl.last_name = 'django'
>>> print(carl)    
django, carl is 30 years old.
>>> carl
<Patient: django, carl is 30 years old.>
>>> 
*************** 여기까지는 객체의 정보만 수정된 상태입니다 ***************
>>> 
>>> carl.save()
>>> 
>>> Patient.objects.all()        
<QuerySet [<Patient: django, carl is 30 years old.>, <Patient: smith, susam is 42 years old.>, <Patient: bolus, mimi is 36 years old.>, <Patient: smith, adam is 40 years old.>, <Patient: marx, karl is 45 years old.>, <Patient: gou, edward is 49 years old.>]>
>>> 
*************** 실제 데이터베이스에도 변경된 것을 알수 있다 ***************

 

 

  • 삭제에 대해서 알아보겠습니다.
>>> 수정한 데이터를 다시 할당하겠습니다
>>> carl = Patient.objects.get(pk=1)
>>> carl
<Patient: django, carl is 30 years old.>

>>> 삭제를 하면 원복을 할수 없습니다. 조심해야 합니다. 삭제된 PK를 보여줍니다.
>>> carl.delete()
(1, {'office.Patient': 1})
>>>

>>> 삭제된 데이터를 pk 값을 통해서 다시 호출하면 없는 값이므로 오류가 발생한다.
>>> Patient.objects.get(pk=1)        
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\MIKE-mini\.conda\envs\django\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\MIKE-mini\.conda\envs\django\lib\site-packages\django\db\models\query.py", line 650, in get
    raise self.model.DoesNotExist(
office.models.Patient.DoesNotExist: Patient matching query does not exist.

>>> 삭제된 데이터가 보이지 않는다
>>> Patient.objects.all()    
<QuerySet [<Patient: smith, susam is 42 years old.>, <Patient: bolus, mimi is 36 years old.>, <Patient: smith, adam is 40 years old.>, <Patient: marx, karl is 45 years old.>, <Patient: gou, edward is 49 years old.>]>
>>>

 

 

삭제된 데이터의 PK값이 없는것을 알 수 있다.