본문 바로가기
FrameWork/Django

App Models

by mansoorrr 2024. 7. 12.

Application(app)의 models.py에 작성한다. app에서 관리할 데이터를 정의하는 곳으로 database와 소통한다.

결국 데이터베이스에서 사용할 table을 만드는 곳이다. 쿼리문을 적을필요 없이 클래스로 만들면 db의 테이블로 만들어진다. 필드명, 필드타입, 유니크, nullable 등을 세팅한다.

 

  • 모델생성(클래스) > 모델적용(makemigrations > migrate) 순으로 진행

 

[model 생성]

  • app의 model.py에 들어가면 django에서 미리 임포트 해놨다(from django.db import models)
  • import한 model을 상속받아 클래스를 만듬
  • 필드타입을 디테일하게 설명할 수록  장고와 데이터베이스가 잘 소통하게 됨
  • 모델을 만들때 관행적으로 모델에 대한 설명을 적음
class House(models.Model):

    ''' 모델에 대한 설명   '''

    name = models.CharField(max_length=140) # 집의 이름
    price = models.PositiveIntegerField() # 일박 가격
    description =  models.TextField() # 집의 설명
    address = models.CharField(max_length=140) #집의 주소
번호 필드명 사용하는 이유 비고
1 CharFiled 길이가 있는 텍스트 max_length=
2 IntegerField 정수  
3 PositiveIntegerField 양수인 정수  
4 TextField 길이가 긴 텍스트  

 

 

[모델적용]

  • 모델을 만들고 저장을 한 후 db를 살펴보면 생성한 모델이 보이지 않음

  • 데이터베이스에 적용하기 위해 migration이 필요
  • cmd에 아래 명령어를 순서대로 입력
    • python manage.py makemigrations 
      • model이 수정되었음을 알림
      • makemigrations할때마다 파일이 생성됨
    • python manage.py migrate
      • db에 적용

1: makemigrations / 2: migrate / 3: migrate 적용된 db모습

 

 

[**상속과 커스텀**]

  • 모델은 상속받아서 만들수도 있고 커스텀 할수도 있다.
  • 만약 Django의 기본 모델을 상속받아서 커스텀 하고 싶다면 기본모델은 건들면 안됨
  • 대신 필드를 덮어쓰는 방식으로 커스텀을 진행한다.
  • 예시: Django에서 기본적으로 제공하는 AbstractUser를 상속받은 User라는 모델이 있다. User모델을 다음과 같이 커스텀 하고자 한다.
    • first_name, last_name 필드는 사용하지 않으려고 한다.
    • name(이름)이라는 필드를 새로 만들고자 한다.
    • is_host(호스트여부)라는 필드를 새로 만들고자 한다.
class AbstractUser(AbstractBaseUser, PermissionsMixin):
    username_validator = UnicodeUsernameValidator(...)
    username = models.CharField(...)
    first_name = models.CharField(_("first name"), max_length=150, blank=True)
    last_name = models.CharField(_("last name"), max_length=150, blank=True)
    email = models.EmailField(_("email address"), blank=True)
    is_staff = models.BooleanField(...)
    is_active = models.BooleanField(...)
    date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
    objects = UserManager(...)
    EMAIL_FIELD = "email"
    USERNAME_FIELD = "username"
    REQUIRED_FIELDS = ["email"]
    
 
 class User(AbstratUser):
  	#사용안함으로 커스텀(editable=False)
	first_name = models.CharField(max_length=150, editable=False)
	last_name = models.CharField(max_length=150, editable=False)
    
    #새롭게 사용할 필드
	name = models.CharField(max_length=150, default="")
	is_host = models.BooleanField(default=False)

 

  • db를 수정, 커스텀 하면 makemigrations로 마이그레이션을 생성하고 migrate로 db에 적용한다.
  • 만약 db에 데이터가 들어있는 상황인데 필드를 추가하게 되면 default를 설정해줘야 한다. default값을 설정 해주면 makemigraions > migrate가 정상 실행 됨
    • non-nullable fileld의 경우(models.BooleanField): default=True or False
    • nullable field의 경우: defualt="", 다른것들
  • 기존의 데이터는 새로운 필드가 추가된 부분에 어떤게 채워져야 할지 모르기 때문이다.

default값을 설정하지 않고 makemigrations했을때 나타나는 에

 

 

[**relationship**]

  • relationship은 RDBMS에서 테이블간 관계를 맺는 것을 의미한다.
  • 관계 형성에는 몇가지가 있다.
    • PK(Primary Key): Django에서는 테이블에 자동으로 id가 생기고 이 컬럼을  pk로 지정한다.
    • FK(Foreign Key): 다른 테이블의 무슨 컬럼을 참조할 것인지 정한다.
      • on_delete: 참조한 테이블의 데이터가 변경되거나 삭제되면 어떻게 할것인지를 정한다
        • CASCADE: 참조한 테이블의 데이터가 삭제되면 본 테이블의 데이터도 삭제한다
        • SET_NULL: 참조한 데이터가 삭제되면 본 테이블의 해당 컬럼은 NULL처리 한다
  • ForeignKey지정
# users app의 User모델을 참조(자동으로 id를 참조하게 됨)
# on_delete=CASCADE 이므로 User모델에서 특정 id가 삭제되면 House모델의 ownser_id가 id인 데이터는 함께 삭제됨

class House(models.Model):
	<생략...>
	owner_id = models.ForeignKey('users.User', on_delete=models.CASCADE)

 

  • ManyToMany
    • Foriegn Key의 경우: 
      • User 1명 --- Room 여러개
      • Room 1개 --- User 1명
    • ManyToMany의 경우
      • Room 1개 --- Amenity 여러개
      • Amenity 1개 --- Room 여러개
    • db에 새로운 테이블이 하나 생성됨
    • related_name을 이용해 거꾸로 검색 가능
# ManyToMany 연결

'''
방 1개 --- 속성 여러개
속성 1개 --- 방 여러개
=> 방여러개 ---- 속성 여러개
'''

class Room(CommonModel):
    name = models.CharField(max_length=100,)    
    owner = models.ForeignKey('users.User', on_delete=models.CASCADE,)
    amenities = models.ManyToManyField('rooms.Amenity', related_name='rooms',) #Amenity.rooms로 Amenity별 room정보를 알 수 있음(backref)

    
class Amenity(CommonModel):
    name = models.CharField(max_length=150,)
    description = models.CharField(max_length=150, null=True, blank=True,)

room_amenities라는 테이블이 생성됨(ManyToMany)

[**choices**]

  • 모델에서 필드를 설정할때 choices를 설정할 수 있다.
  • choices는 필드가 몇가지의 선택지를 가질때 설정한다
    • gender: 남자, 여자
    • language: 한국어, 영어, 일본어, 중국어
    • currency: 원, 달러, 엔
    • grade: 초등학교, 중학교, 고등학교, 대학교
  • 모델안에 클래스를 만들어 적용한다.
  • 이후 admin.py에 적용해주면 됨
class User(AbstractUser):
	
    #choice class
    class GenderChoice(models.TextChoice):
    	'''
        변수 = (db에 저장될 데이터, 관리자패널에서 보여질 데이터)
        이렇게 세팅함
        '''    
    	MALE = ('male', 'Male')
        FEMALE = ('female', 'Female')
        
    
    #새로운 필드 정의
    gender = models.CharField(max_length=10, choices=GenderChoice.choices) #choices 설정(클래스명.choices)

choice설정이 admin패널에서 이렇게 나타남

 

[**Meta**]

  • 모델의 메타정의를 만들때 사용함
  • 여러 parameter를 사용해 모델 조작 가능
    • abstract: 추상클래스로만 사용, 해당 모델을 db에는 저장하지 않음
    • verbose_name_plural: 관리자패널에서 보일 모델의 이름을 정의
class CommonModel(models.Model):
	created_at = models.DateTimeField(auto_now_add=True,) #auto_no_add: 생성된 시간만 자동입력
    modified_at = models.DateTimeField(auto_now=True,) #auto_now: 수정될때마다 수정시간 자동입력
    
    #Meta정의
    class Meta:
    	absrtract = True #추상클래스로만 사용, db에 저장안함

'FrameWork > Django' 카테고리의 다른 글

App User  (0) 2024.07.13
App Admin  (0) 2024.07.12
Application  (0) 2024.07.11
Setup Super User & settings  (0) 2024.07.11
Setup Admin & Migration  (0) 2024.07.11