backend django #5 models FK, ManytoManyField , Meta

eunji hwang·2020년 4월 9일
0

BACKEND-PYTHON-DJANGO

목록 보기
11/28
post-custom-banner

models.py

장고프로젝트에서 models.py는 DB를 작성하는 파일이다.

from django.db import models

장고에서 지원하는 models모듈을 불러 사용하며, Model클래스로 인스턴스를 생성한다.

테이블생성

from django.db import models

class User(models.Model):
    # PK, unique, AI 자동생성
    user_name = models.CharField(max_length=50)
    password  = models.CharField(max_length=200)
    create_at = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now=True)

테이블은 클래스로 생성하며 models.Model을 상속받아 생성한다.
변수는 컬렴명이 되고, models.~~field를 사용해 속성을 지정하게 된다.

PramaryKey, AutoIncrease가 적용되는 id컬럼은 지정하지 않을 경우 장고가 자동으로 생성해준다. 물론 개발자가 직접 지정해도 된다.

models.filed

[
    'AutoField',
    'BLANK_CHOICE_DASH',
    'BigAutoField',
    'BigIntegerField',
    'BinayField',
    'BooleanField',
    'CharField',
    'CommaSeparatedIntegerField',
    'DateField',
    'DateTimeField',
    'DecimalField',
    'DurationField',
    'EmailField',
    'Empty',
    'Field',
    'FieldDoesNotExist',
    'FilePathField',
    'FloatField',
    'GenericIPAddressField',
    'IPAddressField',
    'IntegerField',
    'NOT_PROVIDED',
    'NullBooleanField',
    'PositiveIntegerField',
    'PositiveSmallIntegerField', 
    'SlugField',
    'SmallAutoField',
    'SmallIntegerField',
    'TextField',
    'TimeField',
    'URLField',
    'UUIDField',
]

외부키 : ForeignKey()

filed 속성

# verbose_name은 ForeignKey, ManyToManyField, OneToOneField 빼고 사용할수있음
verbose_name=None, # 이름지정, 첫 인자(옵션), 기본값은 필드명 대체
name=None, 
primary_key=False, # 프라이머리키 지정
max_length=None, # 스트링 길이지정
unique=False, 
blank=False,
null=False, # null 허용하는가
db_index=False,
rel=None,
default=NOT_PROVIDED,
editable=True,
serialize=True,
unique_for_date=None,
unique_for_month=None,
unique_for_year=None,
choices=None,
help_text='',
db_column=None,
db_tablespace=None,
auto_created=False,
validators=(),
error_messages=None

Foreign key field on_delete

Foreingh key 설정을 할때 DB의 참조무결성을 유지하기 위한 속성으로 그 종류와 차이에 대해 알아보자

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=50)
    
class UserProfile(models.Model):
    name = User.ForeignKey(User, on_delete=models.<삭제경우할일>)

1. models.CASCADE

FK가 바라보는 곳이 삭제 될 경우, FK를 포함하는 모델(테이블)이 삭제된다. 1:1 관계일때 설정한다.

2. models.PROTECT

FK가 바라보는 곳이 삭제 될 경우, FK를 포함하는 모델(테이블)이 삭제되지 않도록 보호한다.

3. models.SET_NULL

class UserProfile(models.Model):
    name = User.ForeignKey(User, on_delete=models.SET_NULL, null=True)

FK가 바라보는 곳이 삭제 될 경우, 필드를 유지하여 Null 값으로 교체한다. 해당 필드는 null=True 속성이 들어가 있어야 한다.


on_delete=models.SET_NULL , null=True는 한쌍이다 옆에 꼭 붙여 넣자.. 오늘도 깜빡하고 에러 앞에서 한참을 해멨다!

4. models.SET_DEFAULT

class UserProfile(models.Model):
    name = User.ForeignKey(User, on_delete=models.SET_DEFAULT, default=<기본값>)

FK가 바라보는 곳이 삭제 될 경우, 필드를 유지하여 default 값으로 교체한다. 해당 필드는 default=<기본값> 속성이 들어가 있어야 한다.

5. models.SET()

class UserProfile(models.Model):
    name = User.ForeignKey(User, on_delete=models.SET(<함수>))

6. models.DO_NOTING

FK가 바라보는 곳이 삭제 될 경우, 아무것도 하지 않는다. 참조무결성을 해치므로 비추천!

ManyToManyField()

다:다 관계인 테이블중 1곳에 ManyToManyField를 설정하여 다:다 관계임을 코드로 작성, 중간다리 테이블은 FK로 각 연결되는 테이블을 바라보고 있다고 코드를 작성하자.
ForeignkeyManyToManyField는 바라보는 테이블의 데이터를 가져오는 것이 아닌 바라보고 있다고 알려주는 역할을 한다.

ManyToManyField 가 갖는 인자를 알아보자.

1. 'self' or '테이블명'

셀프 참조일때 첫번째 인자는 'self' 가 된다.
같은 models.py파일에 있는 테이블이라면, 해당 테이블 명을 첫번째 인자로 넣으면 다:다 관계인 테이블을 가르킨다.
만약 다른 app의 models.py에 존재하는 테이블이라면 절대경로 앱이름.테이블명 을 인자로 넘겨주면 된다

class Message(models.Model):
    content    = models.TextField(null = True)
    ## 아래 참조 table User는 같은 파일에 존재하는 User 클래스이며
    from_user  = models.ForeignKey('User', on_delete = models.SET_NULL, null = True, related_name = 'from_user')
    to_user    = models.ForeignKey('User', on_delete = models.SET_NULL, null = True, related_name = 'to_user')
    created_at = models.DateTimeField(auto_now_add = True)
    updated_at = models.DateTimeField(auto_now = True)
    # 아래 song.Playlist 테이블은 앱 song 의 models.py 안의 Playlist 클래스이다.
    # 다른 앱의 모델의 경우 절대경로를 작성하면 된다.
    playlist   = models.ManyToManyField('song.Playlist', through = 'MessagePlaylist')
    song       = models.ManyToManyField('song.Song', through = 'MessageSong')
    is_checked = models.BooleanField(default = False)

    class Meta:
        db_table = 'messages'

2. through='중간테이블'

through는 ManyToManyField일때의 중간테이블이 누구인지를 지정한다.
같은 파일일 경우 클래스 명을, 다른 앱일 경우 절대경로를 넣는다.

3. symmetrical = bool

related_name 을 지정할 경우 해당 데이터에 접근할때 related_name으로 지정한 이름으로 접근 가능하다. 역참조 일때 관계명을 지정하지 않았을 경우 테이블명소문자_set() 으로 접근 가능하다! 만약 테이블명소문자_set()으로 데이터에 접근할때 오류가 난다면 related_name을 확인하자.

Meta 옵션

django meta 문서

class 모델명(models.Model):
    필드 = models.IntegerField()
    
    class Meta:
        unique_together = ('필드a', '필드b') # 셀프참조일때 서로가 같을수 없다.
        ordering = ["필드"] # 순서 정의
        db_table = '테이블명지정'
        verbose_name_plural = "users"

unique_together

셀프 참조일때 인자로 받은 필드들은 서로 같은 수 없다.

db_table

모델에 사용할 데이터베이스 테이블의 이름. 안하면 앱이름.클래스명 으로 등록되니 투머치!하니 이름을 지정해 주기로 하자아~

ordering

객체 목록을 가져올 때 사용하기위한 객체의 정렬, 기본 지정한 필드의 오름차순 정렬.

ordering = ["필드"] # 오름차순
ordering = ["-필드"] # 내림차순
ordering = ["필드A","-필드B"] # 필드A 오름차순 필드B 내림차순
ordering = [F('author').asc(nulls_last=True)] # 쿼리식 가능...

verbose_name_plural

객체의 복수 이름, 이것이 지정되지 않으면 verbose_name+'s'를 사용한다.

profile
TIL 기록 블로그 :: 문제가 있는 글엔 댓글 부탁드려요!
post-custom-banner

0개의 댓글