1) abstract class 만들기
다른 앱에서 사용하는 공통 필드들을 한 곳에 모아서 상속 받아서 사용하면 편하다
Abstract base classes are useful when you want to put some common information into a number of other models.
1. models.py에 다른 곳에서 import할 class를 정의해준다
2. 그 클래스 내부에 Meta class를 만든다
3. abstract = True
=> 이 클래스는 DB가 생성되지 않고 얘를 상속 받는 곳에서 DB가 만들어진다
class TimeStampedModel(models.Model):
""" Time Stamped Model """
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
docs.djangoproject.com/en/3.1/topics/db/models/#abstract-base-classes
* DateTimeField() 옵션
auto_now_add : 모델을 저장할 때 자동으로 현재 날짜를 저장
auto_now : 모델을 생성할 때마다 수시로 날짜를 업데이트
docs.djangoproject.com/en/3.1/ref/models/fields/#datefield
* model의 meta class 옵션들
verbose_name_plural : django admin 화면에서 보여질 이름. 아무것도 안하면 verbose_name에 's'를 붙임
verbose_name : model 이름
ordering : 정렬 기준, -가 붙으면 내림차순, 없으면 오름차순
class RoomType(AbstractItem):
""" RoomType Model Definition """
class Meta:
verbose_name = "Room Type"
ordering = ["name", "-created"]
class Facility(AbstractItem):
""" Facility Model Definition """
class Meta:
verbose_name_plural = "Facilities"
2) ForeignKey
다른 모델에서 정의한 필드를 사용하고 싶을 때 ForeignKey 설정을 한다
일대다 관계(many-to-one relation) : user 1명은 여러 개의 room을 가질 수 있음. room은 user 1명만 가질 수 있다
ex) user에 있는 필드를 room에서 사용하고 싶음
1. user의 models를 import(이름이 겹치니 변경해준다)
2. models.ForeignKey() 안에 user_models.User 를 넣어준다
-> ForeignKey에는 다른 테이블의 id가 들어감(user의 id가 들어감)
1. 에서 users의 models를 import하는 대신 string type으로 "users.User"로 해주면 Django가 메소드를 찾아줌
from core import models as core_models
from users import models as user_models
class Room(core_models.TimeStampedModel):
""" Room Model Definition """
#host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)
host = models.ForeignKey("users.User", on_delete=models.CASCADE)
room_type = models.ForeignKey(RoomType, on_delete=models.SET_NULL, null=True)
docs.djangoproject.com/en/3.1/ref/models/fields/#foreignkey
* ForeignKey로 DB의 table이 연결되어 있으면 review -> room -> user로 몇 단계 건너건너 값을 불러올 수 있다
def __str__(self):
return f'{self.room.host.username} - {self.review}'
* on_delete : ForeignKey가 삭제될 때 어떤 행동을 할지 옵션을 줄 수 있다
- CASCADE : ForeignKey가 삭제되면 이 ForeignKey를 가진 테이블도 삭제함
- PROTECT : ForeignKey와 연결된 테이블을 삭제하기 전 까진 ForeignKey를 삭제할 수 없음
- RESTRICT(3.1에서 새로 생김) : RestrictedError를 발생 시켜서 연관된 object의 삭제를 막음(??)
CASCADE 관계로 되어있고 PROTECT로 해둔 것이 있을 때 PROTECT된 것도 같이 삭제하고 싶을 때 쓰는듯
class Artist(models.Model):
name = models.CharField(max_length=10)
class Album(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
class Song(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
album = models.ForeignKey(Album, on_delete=models.RESTRICT)
위의 관계일 때 아래처럼 설정함
artist 1 ~ album 1~ song1, song2
artist 2 ~ album 2
1) album 1을 삭제 -> song과 RESTRICT 관계이므로 RestrictedError 발생
2) artist 2를 삭제 -> song과 artist 관계가 없어서(그런 걸로 추측...) RestrictedError 발생
3) artist 1을 삭제 -> album1, song1, song2가 함께 삭제됨
code.djangoproject.com/ticket/27272
- SET_NULL : ForeignKey가 삭제되면 ForeignKey의 값을 null로 설정(null=True로 설정해주자)
- SET_DEFAULT : ForeignKey가 삭제되면 ForeignKey의 default 값으로 설정(ForeignKey의 default값을 미리 설정해둬야 사용 가능)
ex) user : aa, room : r1, r2 ..
- CASCADE : r1, r2 모두 삭제됨
- PROTECT : r1, r2 모두 삭제 되기 전까지 삭제 안됨
3) __str__
python의 class는 __init__, __str__ 등 메소드가 미리 정의되어 있다
__str__는 print(), str() 등 class의 instance를 출력할 때 불려짐
-> Django에서 보통 str(obj) 형태로 class를 출력할 때가 많으니 __str__로 어떤 내용을 보여줄 지 적어두면 좋다
from core import models as core_models
from users import models as user_models
class Room(core_models.TimeStampedModel):
""" Room Model Definition """
def __str__(self):
return self.name
docs.djangoproject.com/en/3.1/ref/models/instances/#django.db.models.Model.__str__
realpython.com/lessons/how-and-when-use-str/
4) ManyToManyField : 다대다 관계
room마다 room type을 여러 개 설정할 수 있음, room type도 여러 개의 room을 가질 수 있다
-> 이럴 땐 다대다 관계를 적용함
models.py에 RoomType을 정의하고
- AbstractItem을 따로 만든 이유는 room type, amenity에 공통으로 들어가는 필드를 묶어둠
class AbstractItem(core_models.TimeStampedModel):
""" Abstract Item """
name = models.CharField(max_length=80)
class Meta:
abstract = True
def __str__(self):
return self.name
class RoomType(AbstractItem):
pass
# Room에서 RoomType을 다대다 연결로 사용
class Room(core_models.TimeStampedModel):
room_type = models.ManyToManyField(RoomType, blank=True)
admin 패널에서 RoomType을 조작할 수 있게 등록함. 여러 개를 한번에 등록해도 되는듯!
@admin.register(models.RoomType, models.Facility, models.Amenity, models.HouseRule)
class ItemAdmin(admin.ModelAdmin):
pass
docs.djangoproject.com/en/3.1/ref/models/fields/#manytomanyfield
docs.djangoproject.com/en/3.1/topics/db/examples/many_to_many/
'개발 > AWS' 카테고리의 다른 글
Django 앱 만들기 - admin 패널 꾸미기, QuerySet, UserManager (0) | 2021.01.21 |
---|---|
AWS 솔루션 (0) | 2021.01.20 |
Django 앱 만들기 - startapp으로 만든 앱 수정하기 (0) | 2021.01.18 |
Django 환경 설정 - EC2, ubuntu, pipenv 사용 (0) | 2021.01.14 |
[AWS] Free tier 생성! (0) | 2020.07.05 |
댓글