Django ModelForm 에서 Foreign key 필드 필터해서 보기

장고 ModelForm 을 편하게 쓰고 있는데, 아예 입력 창을 띄울 때 Foreign key로 등록된 필드를 일부 필터링해서 보여주고 싶은 경우가 아주 자주 발생한다. 무슨 overring 하면 될 듯 한데 솔루션을 찾아보자.

 

(2021.11.25) 업데이트

request.POST 데이터를 넘기니깐, 첫번째 인자로 들어가 버려서 원래 작성된 아래 글처럼 선언하면 사용자 변수 위치에 떡 들어가 버려서 오류를 일으킴.

 

그냥 아래처럼 사용자 변수를 받도록 처리하자. 인자를 추가하지 말고

 

참고 사이트 - https://europani.tistory.com/247

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')		# pop을 이용하여 받음	
        super().__init__(*args, **kwargs)

머니머니 해도 구글링이 최고고 stackoverflow (한국의 네이버 지식인은 왜....) 가 최고인듯 하다

검색을 해보니 아래 글이 나온다.

https://stackoverflow.com/questions/48126151/django-modelform-foreign-key-filtering

 

Django ModelForm foreign key filtering

I'm trying to filter foreign key field selections in my model form, but form isn't working. My scripts: forms.py from django import forms from .models import Album, Song class SongCreateForm(forms.

stackoverflow.com

 

말인 즉슨

__init__ 함수를 오버라이딩 해라는 것!!

 

form.py 의 코드에서

from django import forms
from .models import Album, Song

class SongCreateForm(forms.ModelForm):

    class Meta:
        model = Song
        fields = [
            'album',
            'name',
            'is_favorite'
        ]

	def __init__(self, user, *args, **kwargs):
        super(SongCreateForm, self).__init__(*args, **kwargs)
        self.fields['album'].queryset = Album.objects.filter(owner=user)

 

여기에 보는 바와 같이 album 이라는 외부키 참조 필드를 필터링 하는 코드가 __init__ 오버라이딩 함수에 들어가 있다.

아무거나 보여주지 않고 폼을 띄울때 특정 사용자 앨범만 가져오는 코드를 넣어 두는 것이다.

 

당연히 매개변수에는 user를 받아 와야 한다. 즉,

그럼 이 Form 을 불러주는 view 함수에서 어떻게 호출해야 하는지 알아보자.

 

from django.views.generic import CreateView

class SongCreateView(CreateView):
    success_url = '/songs/'
    def get_form(self, form_class=None):
        form_class = SongCreateForm(user=self.request.user)
...

 

위의 코드 처럼 폼을 호출할 때 user 라는 파라미터를 같이 넣어서 불러주면 된다.

 

그럼 __init__ 함수에서 이 변수를 받아 정의된 문장에 의해 필터링이 되고, 

fiels['album'] 은 필터링 된 값만 가지고 보여주도록 할 수 있다.

 

(추가)

 

아래 처럼 기본 값을 넣어 두면, 호출 할 때 이 매개변수를 쓰지 않아도 정상동작 한다.

아래 처럼 하지 않으면 매번 호출 할 때 마다 꼭 user 라는 매개변수를 넣어 줘야 한다.

    def __init__(self, user=None, *args, **kwargs):
        super(ItemForm, self).__init__(*args, **kwargs)
        if user is not None:
            self.fields['album'].queryset = ....

 

 

정보는 위치가 가장 찾기 어려워

Andrea Piacquadio 님의 사진, 출처: Pexels