Django-filter: request.GET์— ํ•„ํ„ฐ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ „๋‹ฌ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๊ธฐ๋ณธ ํ•„ํ„ฐ๋ง

์— ๋งŒ๋“  2015๋…„ 11์›” 06์ผ  ยท  6์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: carltongibson/django-filter

์—ฌ๋Ÿฌ๋ถ„ ๋ชจ๋‘์—๊ฒŒ,

Meta.fields์—์„œ ์ •์˜ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์š”์ฒญ ๊ฐœ์ฒด์—์„œ ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ๊ธฐ๋ณธ ํ•„ํ„ฐ ํ•„๋“œ ๋ฐ ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๊ทธ๋Ÿฌํ•œ ์˜ต์…˜์ด ์—†๋‹ค๋ฉด ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฌด์—‡์„ ์ œ์•ˆํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

๋ฌธ์•ˆ ์ธ์‚ฌ,
์•ˆ๋“œ๋ฆฌ์šฐ์Šค

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

FilterView๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. get_filterset_kwargs ์žฌ์ •์˜๊ฐ€ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.

class MyFilterView(FilterView):
    filterset_class = filters.MyFilter
    # ...
    def get_filterset_kwargs(self, filterset_class):
        kwargs = super(MyFilterView, self).get_filterset_kwargs(filterset_class)
        if kwargs["data"] is None:
            kwargs["data"] = {"is_very_interesting": False}
        return kwargs

ํŽธ์ง‘: ์˜ˆ๋ฅผ ๋“ค์–ด ํŽ˜์ด์ง€ ๋งค๊น€์„ ์‚ฌ์šฉํ•  ๋•Œ ์ด๊ฒƒ์€ ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(b/c ๋ฐ์ดํ„ฐ๋Š” ์—†์Œ์ด ์•„๋‹˜). ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        if kwargs["data"] is None:
            kwargs["data"] = {"is_very_interesting": False}
        elif "is_very_interesting" not in kwargs["data"]:
            kwargs["data"] = kwargs["data"].copy()
            kwargs["data"]["is_very_interesting"] = False

๋ชจ๋“  6 ๋Œ“๊ธ€

์•ˆ๋…•ํ•˜์„ธ์š” @andrius-senulis์ž…๋‹ˆ๋‹ค. django-filter๋Š” ์ผ๋ฐ˜ django ์–‘์‹ ์œ„์— ๊ตฌ์ถ•๋˜์—ˆ์œผ๋ฏ€๋กœ ์ด ์งˆ๋ฌธ์€ "๋ฐ”์šด๋“œ ์–‘์‹์— ๊ธฐ๋ณธ ํ•„๋“œ ๊ฐ’์„ ์–ด๋–ป๊ฒŒ ์ œ๊ณตํ•ฉ๋‹ˆ๊นŒ?"๋กœ ์š”์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด SO ๋‹ต๋ณ€ ์— ๋”ฐ๋ผ ์–‘์‹์— clean_<field_name> ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ธฐ๋ณธ๊ฐ’์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ ๊ธฐ๋ณธ ์–‘์‹ ํด๋ž˜์Šค๋Š” ์ง์ ‘ ๋…ธ์ถœ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•˜์œ„ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค๊ณ  ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค (ํŽธ์ง‘ ์ฐธ์กฐ). ์ฆ‰, ํ•„ํ„ฐ์—๋Š” ๊ธฐ๋ณธ ์–‘์‹ ํ•„๋“œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ํ•„๋“œ๋ฅผ ํ•˜์œ„ ๋ถ„๋ฅ˜ํ•˜๊ณ  clean() ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์กฐ๊ธˆ ๋ฒˆ๊ฑฐ๋กญ์Šต๋‹ˆ๋‹ค. ์˜ˆ,

class DecimalDefaultField(forms.DecimalField):
    def clean(self, value):
        if value is None:
            return 4.0
        return super(DecimalDefaultField, self).clean(value)

class NumberDefaultFilter(filters.NumberFilter):
    field_class = DecimalDefaultField

class MyFilterSet(FilterSet):
    some_field = NumberDefaultFilter(name='some_field')
    ...

๋” ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์‚ฌํ•˜๊ณ  ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

def your_view(request):
    data = request.GET.copy()
    data.setdefault('some_field', 'some_value')

    f = YourFilterSet(data, queryset=YourModel.objects.all())
    ...

ํŽธ์ง‘ํ•˜๋‹ค:
์‹ค์ œ๋กœ FilterSet.Meta ๊ธฐ๋ณธ ์–‘์‹์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ํ•˜์œ„ ๋ถ„๋ฅ˜๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ clean_<field name> ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

class MyForm(forms.Form):
    clean_some_field(self, value):
        ...

class MyFilterSet(FilterSet):
    class Meta:
        model = MyModel
        form = MyForm
        fields = ['some_field']

FilterView๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. get_filterset_kwargs ์žฌ์ •์˜๊ฐ€ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.

class MyFilterView(FilterView):
    filterset_class = filters.MyFilter
    # ...
    def get_filterset_kwargs(self, filterset_class):
        kwargs = super(MyFilterView, self).get_filterset_kwargs(filterset_class)
        if kwargs["data"] is None:
            kwargs["data"] = {"is_very_interesting": False}
        return kwargs

ํŽธ์ง‘: ์˜ˆ๋ฅผ ๋“ค์–ด ํŽ˜์ด์ง€ ๋งค๊น€์„ ์‚ฌ์šฉํ•  ๋•Œ ์ด๊ฒƒ์€ ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(b/c ๋ฐ์ดํ„ฐ๋Š” ์—†์Œ์ด ์•„๋‹˜). ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        if kwargs["data"] is None:
            kwargs["data"] = {"is_very_interesting": False}
        elif "is_very_interesting" not in kwargs["data"]:
            kwargs["data"] = kwargs["data"].copy()
            kwargs["data"]["is_very_interesting"] = False

__init__ ์‚ฌ์šฉํ•˜๋ฉด ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. (์ด๊ฒƒ์€ djangorestframework-filters ์ด์ง€๋งŒ ๋ฐ”๋‹๋ผ django-filter ์™€ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค):

class MyFilter(filters.FilterSet):
    foo = ...

    def __init__(self, data, *args, **kwargs):
        if not data.get('foo'):
            data = data.copy()
            data['foo'] = 'bar'
        super().__init__(data, *args, **kwargs)

__init__ ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š์œผ๋ฉฐ ๋งํฌ์— ์„ค๋ช…๋œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค... https://django-filter.readthedocs.io/en/master/guide/tips.html # ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐ๊ฐ’ ์‚ฌ์šฉ
get_filterset_kwargs ์˜ FilterView ๊ฐ€ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

__init__ ์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๊ธฐ๋ณธ ์–‘์‹/ํ•„ํ„ฐ ๊ฐ’์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์€ ํ˜ผ๋ž€์Šค๋Ÿฝ๊ฑฐ๋‚˜ ๋ถ€์ •์ ์ธ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ๋‚˜์œ ์Šต๊ด€์ด๋ผ๋Š” ์ ์—์„œ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. __init__ ๋˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค(ํšจ๊ณผ์— ๋Œ€ํ•ด ๊ดœ์ฐฎ๋‹ค๋ฉด).

FilterView๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. get_filterset_kwargs ์žฌ์ •์˜๊ฐ€ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.

class MyFilterView(FilterView):
    filterset_class = filters.MyFilter
    # ...
    def get_filterset_kwargs(self, filterset_class):
        kwargs = super(MyFilterView, self).get_filterset_kwargs(filterset_class)
        if kwargs["data"] is None:
            kwargs["data"] = {"is_very_interesting": False}
        return kwargs

ํŽธ์ง‘: ์˜ˆ๋ฅผ ๋“ค์–ด ํŽ˜์ด์ง€ ๋งค๊น€์„ ์‚ฌ์šฉํ•  ๋•Œ ์ด๊ฒƒ์€ ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(b/c ๋ฐ์ดํ„ฐ๋Š” ์—†์Œ์ด ์•„๋‹˜). ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        if kwargs["data"] is None:
            kwargs["data"] = {"is_very_interesting": False}
        elif "is_very_interesting" not in kwargs["data"]:
            kwargs["data"] = kwargs["data"].copy()
            kwargs["data"]["is_very_interesting"] = False

๋‹น์‹ ์€ ๋‚ด ํ•˜๋ฃจ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค!

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰