[장고]FK (foreignkey), ManyToManyField, OneToOneField형식.

권수민·2023년 9월 6일
1

PK와 FK란? : 링크텍스트

저번시간의 PK와 FK를 설명했는데, 좀더 Fk와 그 외의 설명이 필요할거 같아 다시 새로운 글을 팠다.

Django의 모델 필드는 데이터베이스 테이블의 열(Column)을 정의하는데 사용되며, 웹 애플리케이션의 데이터 모델을 구성한다.

그렇다면 먼저 모델의 필드는 어떤 종류가 있을까?

참조:[링크텍스트](Model field reference | Django documentation | Django (djangoproject.com))

대표적인것만 보자면,

CharField:

CharField는 짧은 문자열을 저장하기 위한 필드입니다.
max_length 매개변수로 최대 문자열 길이를 지정해야 합니다.
예: models.CharField(max_length=100)

IntegerField:

IntegerField는 정수 값을 저장하는 데 사용됩니다.
예: models.IntegerField()

FloatField:

FloatField는 부동 소수점 수를 저장하는 데 사용됩니다.
예: models.FloatField()

DateField:

DateField는 날짜를 저장하는 데 사용됩니다.
예: models.DateField()

TimeField:

TimeField는 시간을 저장하는 데 사용됩니다.
예: models.TimeField()

DateTimeField:

DateTimeField는 날짜와 시간을 저장하는 데 사용됩니다.
예: models.DateTimeField()

BooleanField:

BooleanField는 참(True) 또는 거짓(False) 값을 저장하는 필드입니다.
예: models.BooleanField(default=False)

EmailField:

EmailField는 이메일 주소를 저장하는 데 사용됩니다. 입력 값이 유효한 이메일 형식이어야 합니다.
예: models.EmailField(max_length=100)

ImageField:

ImageField는 이미지 파일을 저장하는 데 사용됩니다. 파일 업로드 기능과 함께 사용됩니다.
예: models.ImageField(upload_to='images/')

ForeignKey:

ForeignKey는 다른 모델과의 관계를 표현하는 필드입니다. 다른 모델의 인스턴스와 관련되어 있음을 나타냅니다.
예: models.ForeignKey(related_name='posts', to='Author')

ManyToManyField:

ManyToManyField는 다대다(Many-to-Many) 관계를 표현하는 필드입니다. 여러 모델 인스턴스 간의 관계를 나타냅니다.
예: models.ManyToManyField(related_name='tags', to='Tag')

SlugField:

SlugField는 URL에 사용할 수 있는 문자열을 저장하는 필드입니다. 주로 블로그 글이나 게시물의 제목을 URL 친화적인 형태로 저장할 때 사용됩니다.
예: models.SlugField(max_length=50, unique=True)

AutoField:

AutoField는 자동으로 증가하는 숫자 필드입니다. 주로 데이터베이스의 기본 키(primary key)로 사용됩니다.

좀더 추가적으로 설명할 필드들은 바로 FK와 연결이 많이된 ManyToManyField 와 OnetoOneField이다.

FK 알고 있으면 도움될 것들

1. to속성

다른 앱에서 UserModel(모델이름) 불러올때 from user.models import UserModel 해줘야한다.

from user.models import UserModel

author = models.ForeignKey(user.UserModel, verbose_name = "글쓴이", on_delete=models.CASCADE)

직접적인 모델 임포트 없이 모델의 이름을 문자열로 참조할 수 있다.
이 방법은 순환 참조 문제를 방지하는 데 유용.

author = models.ForeignKey('user.UserModel', verbose_name = "글쓴이", on_delete=models.CASCADE)

2. 필드의 parameter 구조

model. CharField/... 다양한 필드들이 있고,
그 값 속성에 이미 파라미터의 키값이 설정되어져 있다.

이게 무슨말이냐 하면, option키 눌러서 charfield들어가서 option키 눌러 __init__함수로 들어가면 이미

def __init__(
       self,
       verbose_name=None,
       name=None,
       primary_key=False,
       max_length=None,
       unique=False,
       blank=False,
       null=False,
       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,
       db_comment=None,
   ):
   

이러한 순서로 함수구조가 짜여진걸 볼 수가 있다.

순서대로 짠다면 키값없이 바로 value값을 넣어주면 된다.
title = model.CharField("이름","title",False,16)

순서가 아니라면(굳이 써줄 필요가 없다던가) 키값 명시하면된다.
title = model.CharField("이름",max_length=16)

하지만 ForeignKey 만 다르다.

verbose_name이란 속성이 아에 구조에서 없기때문에

	verbose_name: 
    모델의 필드가 어떻게 레이블링 될지를 보다 명확하게 지정하고 싶을 때 사용한다.
    어드민이라든지 페이지에 나타나고, 
    코딩시 이해가 빠르게 되어 적어주는 편이 나을때도 있다.

to = '모델이름'or 'app이름. 모델이름' 가 첫번째 속성이기때문에 UserModel이 바로들어간다.

author = models.ForeignKey(UserModel, verbose_name = "글쓴이", on_delete=models.CASCADE) 

3.ManyToMany 필드

ManyToManyField를 사용하면 Django는 자동으로 "브릿지 테이블" 또는 "중간 테이블"(intermediate table)을 생성한다.

이 테이블은 두 모델 간의 다대다 관계를 저장하는 데 사용하는데,
(한마디로 두테이블이 서로서로를 필요로 하고 다대다 관계에 있으면
즉, 한 저자가 여러 책을 출판할수도 있고, 북에서는 여러 작가가있을 수 있다.)

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)

이렇게 만들어진 테이블 이름은 'book__authors'로 <첫 번째 모델 이름 소문자><두 번째 모델 이름 소문자>형식으로 지정된다.

book_id와 author_id라는 두 개의 외래 키가 포함된다.

중간 테이블에 추가적인 정보를 저장하고 싶다면, through 옵션을 사용하여 직접 중간 모델의 이름을 정의하여 모델링을 해주면 된다.

from django.db import models

class Student(models.Model):
   name = models.CharField(max_length=100)

class Course(models.Model):
   title = models.CharField(max_length=100)
   students = models.ManyToManyField(Student, through='Enrollment')

class Enrollment(models.Model):
   student = models.ForeignKey(Student, on_delete=models.CASCADE)
   course = models.ForeignKey(Course, on_delete=models.CASCADE)
   date_enrolled = models.DateField()
   grade = models.DecimalField(max_digits=5, decimal_places=2)
  1. Course 모델 내의 ManyToManyField에 through='Enrollment' 옵션을 지정 => 중간 테이블로 Enrollment을 사용하겠다고 선언.
  2. Enrollment는 Student와 Course에 대한 외래 키를 포함 +
    추가적으로 date_enrolled 및 grade 필드를 포함

=> 학생이 강좌를 수강할 때마다 Enrollment 객체를 생성하여
해당 학생, 강좌, 등록 날짜 및 성적을 저장

to: 이 속성은 필드가 연결될 다른 모델을 지정

related_name: 이 속성은 역관계에서 사용될 이름을 제공
역관계란 현재 모델이 아닌 다른 모델(이 경우 Tag 모델)에서 현재 모델로의 접근할 이름을 넣어주면 현재모델의 모든 객체에 접근할 수 있게된다.

class Article(models.Model):
    title = models.CharField(max_length=100)
    tags = models.ManyToManyField(related_name='articles', to='Tag')

class Tag(models.Model):
    name = models.CharField(max_length=30)

여기서 Article 모델은 여러 Tag와 연결될 수 있고, 하나의 Tag는 여러 Article과 연결될 수 있습니다.

related_name='articles' 속성 덕분에 Tag 객체에서 연결된 모든 Article 객체에 직접 접근할 수 있습니다.

tag = Tag.objects.get(name="Python")
related_articles = tag.articles.all()  # 이 태그와 관련된 모든 기사를 가져옵니다

여기서는 views.py에 있는 함수 중 모델 값을 가지고 올때 사용된다.
relate_name을 통해 더 직관적인 모델관계를 표현한다.

4. OneToOneField(일대일 관게)

한 모델의 인스턴스가 다른 모델의 한 인스턴스와만 연결될 수 있게되는 것을 말한다.
오직 서로가 서로에게 참조되는 것.

예)하나의 사용자(User)가 하나의 프로필(Profile)만 가질 수 있다

class User(models.Model):
   name = models.CharField(max_length=100)

class Profile(models.Model):
   user = models.OneToOneField(User, on_delete=models.CASCADE)
   bio = models.TextField()

그리고 사실 OneToOne은 따로 명시하지 않는 이유는 필드의 속성중 unique가 있는데 ForeignKey 값이 unique=True인것과 같은것을 뜻하기 때문이다.

unique=True 그 값을 고유하게 유지시켜주겠다는 소리,
즉 참조된 그 값은 현재테이블과의 고유참조가 된것.

예)

class User(models.Model):
    name = models.CharField(max_length=100)

class Profile(models.Model):
    user = models.ForeignKey(User, unique=True, on_delete=models.CASCADE)
    bio = models.TextField()

4. On_delete 속성

이 속성은 관련된 객체가 삭제될 때 어떤 동작을 해야하는지를 정의한다.

여기서 on_delete 속성에 대해서 얘기하자면 6가지의 속성이 있고,

OneToOneField과 ForeignKey에서 사용되는 속성이다.

ManyToManyField에서 한 객체를 삭제해도 다른 모델의 객체에는 영향을 주지않고(이어져 있는 다른 2개의 모델들), 오직 중간테이블에서 해당객체와 관련된 모든 레코드(연결, 열)만 제거되기 때문에 이속성 자체가 필요가 없다.

필드에서 제일 많이쓰는 models.CASCADE 와 models.SET_NULL 관해 설명하자면,

models.CASCADE:

관련된 객체가 삭제될 때, ForeignKey나 OneToOneField로 연결된 객체도 삭제된다.

즉, 다른 연결된 객체도 삭제되는것.

예) 글쓴이 - 블로그
=> 글쓴이가 삭제되면 글쓴이가 쓴 모든 포스팅도 삭제된다.

models.SET_NULL:

관련된 객체가 삭제될 때 ForeignKey 필드의 값을 NULL로 설정합니다. 이 옵션을 사용하려면 null=True 속성이 필드에 설정되어 있어야 한다.

즉, 다른 연결된 객체는 남아있고 삭제된 해당 객체만 NULL상태로 연결된것.

예) 글쓴이 - 블로그
=> 글쓴이가 삭제되면 글쓴이가 쓴 모든 포스팅에서 글쓴이가 삭제된다.

profile
초보개발자

0개의 댓글