본문으로 바로가기
 

Model field reference | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

상당히 긴 문서입니다. model을 디자인하는데 유용하게 사용되므로 작성할 때 종종 와서 찾아 보는 것이 좋습니다.

 

하나씩 설명하기보다, 디자인한 모델을 가져와서 훗날 재활용 및 참고하는 게 더 적절해 보입니다.

 

 

우선 기본적인 사항들을 정리했습니다.

 

  • ImageField를 사용하려면 Pillow를 설치해야 합니다. 필자는 pipenv 가상환경을 사용하고 있으므로 pipenv install Pillow로 설치했습니다.
  • blank는 required의 문제이며 null은 DB에 빈 값을 허용하는 지의 문제입니다. 따라서, null=True만 설정하고 빈 값으로 제출하려고 하면 required라며 팅겨냅니다.
  • blank 설정이 안되어 있으면 required이므로 모델에서 볼드체로 표시됩니다.
  • CharField의 choices를 통해 셀렉트 박스를 만들 수 있습니다.
class User(AbstractUser):

    """ Custom User model """

    GENDER_MALE = "male"
    GENDER_FEMAIL = "female"
    GENDER_OTHER = "other"

    # 첫 인자는 DB에 저장되고 두번째 인자는 form에 보여집니다
    # (actual value, human readable name)
    GENDER_CHOICES = (
        (GENDER_MALE, "Male"),
        (GENDER_FEMAIL, "Female"),
        (GENDER_OTHER, "Other"),
    )

    LANGUAGE_CHOICES = (
        ("en", "English"),
        ("kr", "Korean"),
    )

    CURRENCY_CHOICES = (
      ("usd", "USD"),
      ("krw", "KRW"),
    )

    # ImageField는 Pillow라는 패키지를 설치해야 합니다. multer 같은 개념입니다.
    avatar = models.ImageField(null=True, blank=True)

    # CharField는 max_length가 필수값이며 choices로 select box를 만들 수 있습니다
    # max_length은 DB 레벨에서의 제한입니다. 사용자에게 보여지는 문자열의 제한이 아닙니다.
    gender = models.CharField(choices=GENDER_CHOICES,
                              max_length=10, default=GENDER_MALE,
                              null=True, blank=True)

    # TextField
    bio = models.TextField(default="", blank=True)

    # DateField는 달력입니다.
    birthday = models.DateField(null=True, blank=True)

    language = models.CharField(
        choices=LANGUAGE_CHOICES, default="en", max_length=2, null=True, blank=True)

    currency = models.CharField(
        choices=CURRENCY_CHOICES, max_length=6, default="usd", null=True, blank=True)

    # BooleanField는 단순한 버튼입니다
    superhost = models.BooleanField(default=False)

 

 

Abstract Model을 만들어 보았습니다. abstract 속성을 True로 두기만 하면 됩니다.

Meta에 속성에 대해서는 다음 문서를 참고합시다. (3.0 버전) 생각보다 짧아서 금방 익힐 수 있습니다.

 

 

Model Meta options | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

 

from django.db import models

# Create your models here.


class TimeStampedModel(models.Model):

    """This is TimeStamped Model"""

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    # abstract가 True면 DB에는 등록되지 않습니다.
    class Meta:
        abstract = True

 

 

IntergerField, TimeField를 눈 여겨 볼만 합니다.

class Room(core_models.TimeStampedModel):

    """Room Model Definition"""
    name = models.CharField(max_length=140)
    description = models.TextField()
    country = CountryField()
    city = models.CharField(max_length=80)
    price = models.IntegerField()
    address = models.CharField(max_length=140)
    guests = models.IntegerField()
    beds = models.IntegerField()
    bedrooms = models.IntegerField()
    baths = models.IntegerField()
    check_in = models.TimeField()
    check_out = models.TimeField()
    instant_book = models.BooleanField(default=False)
    host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)

 

 

여기서 DateField, DateTimeField, TimeField의 차이를 알아봅시다.

 

왼쪽이 TimeField 오른쪽이 DateField입니다.

DateTimeField는 둘을 섞어서 날짜와 시간을 동시에 지정할 수 있는 field입니다.

 

 

 

Meta 클래스를 이용해서 verbose_name과 ordering을 수정할 수 있습니다.

 

 

Model Meta options | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

from django.db import models
from core import models as core_models
from django_countries.fields import CountryField
from users import models as user_models

# Create your models here.


class AbstractItem(core_models.TimeStampedModel):

    """ Abtract Item """
    name = models.CharField(max_length=80)

    class Meta:
        abstract = True

    def __str__(self):
        return self.name


class RoomType(AbstractItem):

    """RoomType Model Definition"""

    class Meta:
        verbose_name = "Room Type"
        ordering = ['created']


class Amenity(AbstractItem):

    """Amenity Model Definition"""

    class Meta:
        verbose_name_plural = "Amenities"


class Facility(AbstractItem):

    """A Facility Model Definition"""

    pass


class HouseRule(AbstractItem):

    """A Rule Model Definition"""

    class Meta:
        verbose_name = "House Rule"


class Room(core_models.TimeStampedModel):

    """Room Model Definition"""

    name = models.CharField(max_length=140)
    description = models.TextField()
    country = CountryField()
    city = models.CharField(max_length=80)
    price = models.IntegerField()
    address = models.CharField(max_length=140)
    guests = models.IntegerField()
    beds = models.IntegerField()
    bedrooms = models.IntegerField()
    baths = models.IntegerField()
    check_in = models.TimeField()
    check_out = models.TimeField()
    instant_book = models.BooleanField(default=False)

    # 1대 다 관계. 하나의 User에 여러개의 Room이 있음을 의미.
    # on_delete는 User가 삭제되었을 때 무엇을 해야 하는 지를 지정합니다.
    # CASCADE는 User와 연결된 Room도 삭제하라는 의미입니다.
    host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)

    room_type = models.ForeignKey(
        RoomType, on_delete=models.SET_NULL, null=True)

    # 다대 다 관계. 여러 Amenity가 여러 Room에 있을 수 있음을 의미
    amenity = models.ManyToManyField(Amenity)
    facility = models.ManyToManyField(Facility)
    house_rules = models.ManyToManyField(HouseRule)

    def __str__(self):
        return self.name

 

ManyToManyField로 설정하면 신기하게도 패널에서 자동으로 (s)를 붙여서 보여줍니다.

 

class Amenity(AbstractItem):

    """Amenity Model Definition"""

    pass

amenity = models.ManyToManyField(Amenity)

다음과 같이 단수로 적어줬음에도(s)가 붙는 것을 볼 수 있습니다. 그러나, amenities가 맞는 표현입니다.

 

따라서 다음과 같이 메타 클래스를 통해 수작업으로 설정해주도록 하겠습니다. (verbose_name_plural)

 

 

Model Meta options | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

class Amenity(AbstractItem):

    """Amenity Model Definition"""

    class Meta:
        verbose_name_plural = "Amenities"

amenity = models.ManyToManyField(Amenity)

 

verbose_name을 사용할 수도 있습니다. 이 경우 자동으로 s를 붙여주게 됩니다.

사실 귀찮아서 그냥 verbose_name_plural로 통일하는 경우가 많습니다.

 

class HouseRule(AbstractItem):

    """A Rule Model Definition"""

    class Meta:
        verbose_name = "House Rule"

 

 

ordering을 통해 해당 모델 내부의 요소들을 정렬할 수도 있습니다.

(https://docs.djangoproject.com/en/3.0/ref/models/options/#ordering)

주의할 점도 보이네요. Ordering is not a free operation. Each field you add to the ordering incurs a cost to your database.

 

class RoomType(AbstractItem):

    """RoomType"""

    class Meta:
        ordering = ["created"]

내부의 요소를 기준으로 ordering을 할 수 있으므로 저는 created를 기준으로 순서를 배치해봤습니다.

 

 

 

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체