회원가입

[리팩토링] 3. Django Admin ManyToMany 필드 버그 수정

Beany 2024-05-05

기존에는 Django Admin 에서 Tag 를 정의해서 저장하면 ManyToManyField 로 정의되어있는 Tag 가 바로 저장이 되지 않는 버그가 있었습니다.

 

[ AS-IS 코드 ]

class Post(TimeStampedModel):
    ...
    def_tag = models.CharField(max_length=150, null=True, blank=True)
    tag_set = models.ManyToManyField('Tag', blank=True)

    ...    
    def tag_save(self):
        tags = re.findall(r'#(\w+)\b', self.def_tag)

        if not tags:
            return

        for t in tags:
            tag, tag_created = Tag.objects.get_or_create(tag_name=t)
            self.tag_set.add(tag)

    def save(self, *args, **kwargs):
        saved = super(Post, self).save(*args, **kwargs)
        # TAG 저장
        if self.def_tag:
            self.tag_save()
        return saved

기존 코드를 보면 `Post` Model 에서 save 메서드를 오버라이드 해서 Tag 를 저장했습니다.
하지만 이 방식은 Django Admin 에서 바로 작동하지 않았습니다.

관련 이슈는 아래 링크에 보면 됩니다.

https://stackoverflow.com/questions/1925383/issue-with-manytomany-relationships-not-updating-immediately-after-save/1925784#1925784

 

[ TO-BE 코드 ]

기존의 코드는 불필요한 코드를 제거하고 아래와 같이 save_related 를 오버라이드 해서 문제를 해결했습니다.

class Post(TimeStampedModel):
    ...
    def_tag = models.CharField(max_length=150, null=True, blank=True)
    tag_set = models.ManyToManyField('Tag', blank=True)

    ...    
    def tag_save(self):
        tags = re.findall(r'#(\w+)\b', self.def_tag)

        if not tags:
            return

        for t in tags:
            tag, tag_created = Tag.objects.get_or_create(tag_name=t)
            self.tag_set.add(tag)

 

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    ...
    def save_related(self, request, form, formsets, change):
        super().save_related(request, form, formsets, change)
        instance = form.instance
        if instance.def_tag:
            instance.tag_save()

 

0 0
블로그 일기
제 블로그의 고도화 과정을 설명합니다. 이는 코드 리팩토링과 추가된 기능들에 대해 기록하기 위한 게시판입니다. 어떤 기능이 추가되었는지, 무엇이 개선되었는지 등 고도화되는 과정을 자세히 다룰 예정입니다.
Yesterday: 456
Today: 166