Django-filter: рд╢реНрд░реЗрдгреА рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП URL рдореЗрдВ рдХрд╕реНрдЯрдо рдирд╛рдо?

рдХреЛ рдирд┐рд░реНрдорд┐рдд 20 рд╕рд┐рддре░ 2015  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: carltongibson/django-filter

рдореИрдВ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛ рдХреЗ рд▓рд┐рдП рдпреВрдЖрд░рдПрд▓ рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдП рдЧрдП рдлрд╝реАрд▓реНрдб рдирд╛рдореЛрдВ рдХрд╛ рдирд╛рдо рдмрджрд▓рдирд╛ рд╕рдВрднрд╡ рд╣реИ рдпрд╛ рдирд╣реАрдВред
рд╡рд░реНрддрдорд╛рди рдореЗрдВ

class TransactionFilter(django_filters.FilterSet):
    created = django_filters.DateFromToRangeFilter()
    class Meta:
        model = models.Transaction
        fields = ('created', )

рдФрд░ рдЕрдиреБрд░реЛрдз рджрд┐рдЦрддрд╛ рд╣реИ

/api/transaction?created_0=2015-01-01&created_1=2015-01-02

рдпрд╣ рдареАрдХ рд╕реЗ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рд╕рд╣рдЬ рдирд╣реАрдВ рд╣реИред рдореИрдВ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рдореИрдВ рд╢реНрд░реЗрдгреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдирд╛рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП

/api/transaction?created_since=2015-01-01&created_until=2015-01-02

рдзрдиреНрдпрд╡рд╛рдж, рд╣рд╛рдХреАред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП MultiWidget рдЙрдк-рд╡рд░реНрдЧреАрдХрд░рдг рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ; рдореИрдВрдиреЗ рдлрд╝реАрд▓реНрдб рдирд╛рдореЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ start рдФрд░ end рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛:

from django.utils.safestring import mark_safe

from django_filters.fields import DateRangeField
from django_filters.filters import RangeFilter
from django_filters.widgets import RangeWidget


class StartEndRangeWidget(RangeWidget):
    """
    A range widget that uses 'start' and 'end' instead of '0' and '1'.
    """

    attr_names = ('start', 'end')

    def render(self, name, value, attrs=None):
        if self.is_localized:
            for widget in self.widgets:
                widget.is_localized = self.is_localized

        # value is a list of values, each corresponding to a widget
        # in self.widgets.
        if not isinstance(value, list):
            value = self.decompress(value)

        output = []
        final_attrs = self.build_attrs(attrs)
        id_ = final_attrs.get('id')

        for i, widget in enumerate(self.widgets):
            try:
                widget_value = value[i]
            except IndexError:
                widget_value = None

            if id_:
                final_attrs = dict(final_attrs,
                                   id='%s_%s' % (id_, self.attr_names[i]))

            output.append(widget.render(name + '_%s' % self.attr_names[i],
                                        widget_value, final_attrs))

        return mark_safe(self.format_output(output))

    def value_from_datadict(self, data, files, name):
        return [widget.value_from_datadict(data, files,
                                           name + '_%s' % self.attr_names[i])
                for i, widget in enumerate(self.widgets)]


class StartEndDateRangeField(DateRangeField):
    """
    A DateRangeField that uses 'start' and 'end'.
    """

    widget = StartEndRangeWidget


class StartEndDateFromToRangeFilter(RangeFilter):
    """
    A RangeFilter that uses 'start' and 'end'.
    """

    field_class = StartEndDateRangeField

рд╕рднреА 3 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рд╣рдореНрдоред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рдЙрддреНрддрд░ _рдирд╣реАрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣реИ - рдЬрдм рддрдХ рдЖрдк рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рдХреЛ рдЧрдВрджрд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ ...

_0, _1 рдЙрдкрд╛рдВрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рд╕рднреА рддрд░рд╣ рд╕реЗ django.forms.widgets.MultiWidget.render рд╕реЗ рдЖрддрд╛ рд╣реИред ( RangeFilter RangeField рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдЬреЛ RangeWidget рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдЬреЛ MultiWidget рдЙрдкрд╡рд░реНрдЧ рд╣реИред)

рдЖрдк рдЬреЛ рдирд╛рдордХрд░рдг рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЙрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк render рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рд╣реИрдВред рдЖрдкрдХреЛ рдПрдХ рдорд┐рд▓рд╛рди value_from_datadict рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП MultiWidget рдЙрдк-рд╡рд░реНрдЧреАрдХрд░рдг рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ; рдореИрдВрдиреЗ рдлрд╝реАрд▓реНрдб рдирд╛рдореЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ start рдФрд░ end рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛:

from django.utils.safestring import mark_safe

from django_filters.fields import DateRangeField
from django_filters.filters import RangeFilter
from django_filters.widgets import RangeWidget


class StartEndRangeWidget(RangeWidget):
    """
    A range widget that uses 'start' and 'end' instead of '0' and '1'.
    """

    attr_names = ('start', 'end')

    def render(self, name, value, attrs=None):
        if self.is_localized:
            for widget in self.widgets:
                widget.is_localized = self.is_localized

        # value is a list of values, each corresponding to a widget
        # in self.widgets.
        if not isinstance(value, list):
            value = self.decompress(value)

        output = []
        final_attrs = self.build_attrs(attrs)
        id_ = final_attrs.get('id')

        for i, widget in enumerate(self.widgets):
            try:
                widget_value = value[i]
            except IndexError:
                widget_value = None

            if id_:
                final_attrs = dict(final_attrs,
                                   id='%s_%s' % (id_, self.attr_names[i]))

            output.append(widget.render(name + '_%s' % self.attr_names[i],
                                        widget_value, final_attrs))

        return mark_safe(self.format_output(output))

    def value_from_datadict(self, data, files, name):
        return [widget.value_from_datadict(data, files,
                                           name + '_%s' % self.attr_names[i])
                for i, widget in enumerate(self.widgets)]


class StartEndDateRangeField(DateRangeField):
    """
    A DateRangeField that uses 'start' and 'end'.
    """

    widget = StartEndRangeWidget


class StartEndDateFromToRangeFilter(RangeFilter):
    """
    A RangeFilter that uses 'start' and 'end'.
    """

    field_class = StartEndDateRangeField

рдЕрд░реЗ @beaugunderson , рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд╣реИ рдХрд┐ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ (рдЬреИрд╕реЗ рдореЗрд░рд╛) lt/gt рдХреЗ рд╕рд╛рде рджреЛ рджрд┐рдирд╛рдВрдХ рдлрд╝реАрд▓реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

blueyed picture blueyed  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

nhuzaa picture nhuzaa  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jwineinger picture jwineinger  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

xtrinch picture xtrinch  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

lalzada picture lalzada  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ