1)

OneToOneField는 외래키에서 unique=True 옵션을 설정한 것과 유사하지만 reverse의 경우에서 다르다. User:Profile 관계라고 했을 때, 외래키에서 profile.user_set.first()의 결과값은 O2O에서는 profile.user의 결과값과 같다.(물론 에러가 발생하는 양상도 다르다.)

2)

from django.conf import settings

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    address = models.CharField(max_length=100)
    zipcode = models.CharField(max_length=6)
+
from .models import Profile

@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
    pass

accounts 앱을 만들어주고 프로젝트 폴더의 settings.py에 설정해주었다. 그리고 앱에 urls.py 파일을 만들고 urlspatterns를 정의해준 다음 프로젝트 폴더의 urls.py에서 include할 수 있도록 해주었다.

accounts 앱의 models.py에는 Profile 클래스와 user 필드를 정의해주었다. 이 과정에서 django.conf의 settings를 가져와서 AUTH_USER_MODEL을 참조했다. 현재 활성화된 모델을 얻는 함수가 get_user_model()임을 알아두자.

모델을 정의한 뒤에는 makemigrations, migrate로 마무리해주면 db에 accounts_profile로 테이블이 생성됐음을 예상할 수 있다.

이를 admin.py에 등록해주고 마무리했다.

3)

class Item(models.Model):
    tag_set = models.ManyToManyField('Tag', blank=True)
+
class Tag(models.Model):
    name = models.CharField(max_length=10, unique=True)

Tag 클래스가 더 뒤에 정의되어 있어서 'Tag' 형식으로 참조했고, Tag 없이도 Item 인스턴스를 생성할 수 있도록 blank=True로 처리했다. Tag는 저장소 개념으로 사용되기 때문에 unique=True로 처리했다.

makemigrations, migrate를 진행하고 db brower for sqllite에서 확인해보면, gallery_item와 gallery_tag db table 말고 gallery_item_tag_set db table이 생겼음을 확인할 수 있다. 이렇게 중간 테이블이 필요한 부분이 외래키와 O2O 필드와 다른 점이다.

db를 확인할 때 post.tag_set.all()은 정의된 이름 tag_set을 그대로 사용하는 것이고, tag.post_set.all()은 related_name으로 'post'와 'set'이 합쳐진 것으로 이해하면 좋을 것이다.

4)

최초 프로젝트를 생성하고 migrate(앱 이름 없이)를 진행하기 전에는 sqlite 파일이 존재하지 않다가 진행 후에 생기는 이유는 settings.py의 INSTALLED_APPS에 포함된 기본 앱들(django.contrib) 에 모델들과 migrations 내역이 있기 때문이다.

migrations 파일을 열어보면 migration 클래스가 migrations.Migration을 상속하는 부분과 dependencies, operations로 이루어졌음을 확인할 수 있다.

0개의 댓글