Django OneToOneField로 연결된 model 자동 생성
서론
공부 삼아 만들던 중 기억하기 위해 쓰는 글입니다.
필자가 만들던 코드를 그대로 가져오므로 예시가 좀 이상할 수 있습니다.
본문
자동으로 생성해주는 코드는 django docs의 signals를 보면 된다
본문을 조금 떼어다 번역해보자면
다른 곳에서 작업이 발생할 때 알림을 받을 수 있도록 도와주는 signal dispather가 포함되어 있습니다.
Singerd을 통해 특정 sender는 어떤 조치가 취해졌음을 receiver에게 알릴 수 있습니다.
즉 singnal을 보내고, receiver로 받아서 그 뒤에 할 일을 정하는 것이다.
물론 이 글에서는 연결된 모델을 생성하는 걸 보여주겠다.
먼저 Video와 Post가 OneToOneField로 연결되어있는 상태를 보여주는 코드 예시이다.
여기서는 Video 생성 시 Post가 자동 생성되도록 만들겠다.
class Video(models.Model):
author = models.ForeignKey(get_user_model(), on_delete=models.RESTRICT)
video = models.FileField(upload_to='board/post/%Y/%m/%d/', validators=[
FileExtensionValidator(allowed_extensions=['avi', 'mp4', 'mkv', 'mpeg', 'webm'])])
...
class Post(TimeModel):
title = models.CharField(max_length=100)
video = models.OneToOneField(Video, on_delete=models.CASCADE, related_name="post_video", unique=True)
...
여기서는 receiver 데코레이터를 사용하여 자동생성을 구현했다.
receiver로 post_save라는 signal을 받아 그 뒤에 할 일을 정하는데
post_save로 넘어온 Video 객체는 instance에 남아있다.
sender: signal 보내는 객체,
instance: signal을 보낸 객체에서 만들어진 object,
created: 만들어졌는지 여부의 boolean
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Video)
def create_Post(sender, instance, created, **kwargs):
name = os.path.basename(instance.video.name).split(".")[0]
if created:
if not hasattr(instance, 'Post'):
Post.objects.create(video=instance, title=name)
그래서 created가 됐다면 hasattr로 Post객체에 instance가 들어있지 않는다면
Post.objects.create() 하여 Post object를 생성해주게 된다.
단 주의사항으로
blank=True나 default 같은 조건을 정하지 않았다면 빈 필드 때문에 에러가 발생할 수 있다.
참조
https://docs.djangoproject.com/en/3.2/ref/signals/#post-save
https://docs.djangoproject.com/en/3.2/ref/signals/
https://docs.djangoproject.com/ko/3.0/_modules/django/core/files/uploadedfile/