Django-filter: contrib.postgres JSONField рдХреЗ рд▓рд┐рдП рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░реЗрдВ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 4 рдЬреВрди 2016  ┬╖  16рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: carltongibson/django-filter

рдпрд╣ Google рдЪрд░реНрдЪрд╛ рд╕рдореВрд╣ рдореЗрдВ рд╢реБрд░реВ рд╣реБрдЖ:
https://groups.google.com/forum/#!topic/django -filter/RwNfoWsdeLQ

рдореБрдЭреЗ django-filter рдХреЗ рд╕рд╛рде contrib.postgres JSONFields рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИред

рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдлрд╝рд┐рд▓реНрдЯрд░ рд╣реИ рдЬреЛ рдХреБрдЫ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред рдпрд╣ рдЬрд┐рддрдирд╛ рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдерд╛ рдЙрд╕рд╕реЗ рдХрд╣реАрдВ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ рдХрд┐ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдкрдиреЗ JSON рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рдордп рд╕реЗ рдкрд╣рд▓реЗ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рдЖрдк IntegerField рдЬреИрд╕реА рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдХреЗ рд╕рд╛рде рдХрд░рддреЗ рд╣реИрдВред рдореИрдВ рд╢рд╛рдпрдж рдЗрд╕реЗ рдЕрддреНрдпрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдБред

рдпрд╣рд╛рдБ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдлрд╝рд┐рд▓реНрдЯрд░ рд╣реИ рдЬреЛ рдореЗрд░реЗ JSONField рдХреЛ рд╣рд┐рдЯ рдХрд░рддрд╛ рд╣реИ
http://127.0.0.1:8000/api/v1/craters?data= рдЕрдХреНрд╖рд╛рдВрд╢:рдлреНрд▓реЛрдЯ :-57:lte~!@!~ рдЙрдореНрд░:str :рдкреАрд╕реА

рдпрд╣рд╛рдБ рдореЙрдбрд▓ рдФрд░ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛрдб рд╣реИ:
https://gist.github.com/jzmiller1/627071f555186cd1a58bb8f065205ff7

рдореИрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рдЦрд┐рд▓рд╡рд╛рдбрд╝ рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреВрдВрдЧрд╛ред рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдХреЛрдИ рд╡рд┐рдЪрд╛рд░ рдпрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╣реИ рддреЛ рдХреГрдкрдпрд╛ рдореБрдЭреЗ рдмрддрд╛рдПрдВ ...

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

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ JSONFilter рдХреЛ jsonfield__a_random_key=value рдЬреИрд╕реЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдирд╛ рд╡рд╛рдХрдИ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд╣реЛрдЧрд╛ред рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕реЗ objects.filter рд╡рд┐рдзрд┐ рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╢рд╛рдпрдж рдЯреНрд░реЗрдбрдСрдлрд╝ рдлрд╝рд┐рд▓реНрдЯрд░ рд╕рддреНрдпрд╛рдкрди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?

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

рд╣рд╛рдп @ jzmiller1ред рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ? рдирд╣реАрдВ рдмрддрд╛ рд╕рдХрддреЗ рдХрд┐ рдЖрдк рд╣реИрдВ:

  • рдПрдХ рд╕рд╛рдорд╛рдиреНрдп JSONFilter рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ JSONField рдХреЗ рдЕрдВрджрд░ рдХрд┐рд╕реА рднреА рдордирдорд╛рдиреА рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рдкреВрдЫрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред рдпрд╛,
  • рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ (рдЕрдХреНрд╖рд╛рдВрд╢, рдЖрдпреБ) рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣рд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЗ рдХреНрд░реЗрдЯрд░ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рд╣реИрдВ data ред рдпреЗ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдЖрдкрдХреА data рдХреА рд╕реНрдХреАрдорд╛ рд╣реЛрдВрдЧреАред

рдкреВрд░реНрд╡ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рдкрд╛рдпрд╛ рд╣реИ рдХрд┐ рдЬрдЯрд┐рд▓рддрд╛ рдпрд╣ рд╣реИ рдХрд┐ JSONField рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рд╕реНрдХреАрдорд╛рд▓реЗрд╕ рд╣реИред рд╕реНрдХреАрдорд╛ рдХреЗ рдмрд┐рдирд╛, рдЖрдк рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдлрд╝рд┐рд▓реНрдЯрд░ рдЬреЗрдирд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдирд╣реАрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдкрдХрд╛ рдореЗрдердбрдлрд┐рд▓реНрдЯрд░ рдЗрд╕рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рднреА рдордирдорд╛рдиреА рд╡рд┐рд╢реЗрд╖рддрд╛ рд▓реБрдХрдЕрдк рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдЙрди рд▓реБрдХрдЕрдк рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрде рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, ?data=latitude:char:PC:isnull рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдирд┐рд░рд░реНрдердХ рд╣реИред рдпрд╣рд╛рдВ рдЬреЛ рднреА рд╕рдорд╛рдзрд╛рди рд╣реИ, рдЙрд╕рдХреЗ рд▓рд┐рдП рдЯреНрд░реЗрдбрдСрдлрд╝ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдордирдорд╛рдирд╛ рдлрд╝рд┐рд▓реНрдЯрд░ рд▓реБрдХрдЕрдк рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдПрдХ рдорд╛рдиреНрдп рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛ рд╕реНрдХреАрдорд╛ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рдХрд┐рд╕реА рддрд░реАрдХреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред

рджреВрд╕рд░реЗ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдзрд╛рди рд╡рд░реНрдмреЛрдЬрд╝/рдердХрд╛рдК рд╣реИ, рд▓реЗрдХрд┐рди рд╕реАрдзрд╛ рд╣реИред

class CratersFilter(filters.FilterSet):
    latitude = filters.NumberFilter(name='data__latitude', lookup_expr='exact')
    latitude__lt = filters.NumberFilter(name='data__latitude', lookup_expr='lt')
    latitude__gt = filters.NumberFilter(name='data__latitude', lookup_expr='gt')
    latitude__isnull = filters.BooleanFilter(name='data__latitude', lookup_expr='isnull')
    # not sure if 'isnull' is a valid lookup for JSONFields - just demonstrating that 
    # different lookups expect different value types.

    age = filters.CharFilter(name='data__age', lookup_expr='exact')
    ...

рддрдм рдЖрдкрдХреА рдХреНрд╡реЗрд░реА рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧреА:

http://127.0.0.1:8000/api/v1/craters?latitude__lte=-57&age=PC

рдореЗрд░рд╛ рд▓рдХреНрд╖реНрдп рдПрдХ рд╕рд╛рдорд╛рдиреНрдп JSONFilter рдмрдирд╛рдирд╛ рд╣реИ рдЬреЛ JSONField рдХреЗ рдЕрдВрджрд░ рдХрд┐рд╕реА рднреА рдордирдорд╛рдиреА рд╡рд┐рд╢реЗрд╖рддрд╛ рдкрд░ рдкреНрд░рд╢реНрдиреЛрдВ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред рдореИрдВ рдЬрд┐рд╕ рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЙрд╕рдХреЗ рд▓рд┐рдП рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдиреВрдВрдЧрд╛ рдХрд┐ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдХреНрд░реЗрдЯрд░ рдХреЗ рдбреЗрдЯрд╛ рдХреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╡рд╣рд╛рдВ рдХреЛрдИ рдХреБрдВрдЬреА рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдвреВрдВрдв рд░рд╣рд╛ рд╣реВрдВ рддреЛ рдореИрдВ рдЙрд╕рд╕реЗ рдкреВрдЫрддрд╛рдЫ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрд▓реБрдХрдЕрдк рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдорд╛рдиреНрдп рдХрд░рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрдерддрд╛ рд╣реИ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдХреНрд╡реЗрд░реА рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдпрд╣ рдорд╣рд╕реВрд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдХреНрд╡реЗрд░реА рдирд┐рд░рд░реНрдердХ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд╣реИред

рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореИрдВ рдЬреЛ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рд╡рд╣ рд╕рдордп рдХреА рдмрд░реНрдмрд╛рджреА рд╣реИ рдпрд╛ рдирд╣реАрдВред рдореИрдВ рдЬреЛ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЙрд╕рдХреЗ рд▓рд┐рдП рд╡рд╣рд╛рдВ рдПрдХ рдмреЗрд╣рддрд░ рд╕рдорд╛рдзрд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдореИрдВ рдЙрддреНрд╕реБрдХ рдерд╛ рдЕрдЧрд░ рдХрд┐рд╕реА рдиреЗ рдкреНрд░рдореБрдЦ рдореБрджреНрджреЛрдВ рдХреЛ рджреЗрдЦрд╛ рдЬреЛ рдЗрд╕реЗ рд╕рдВрднрд╡ рд╣реЛрдиреЗ рд╕реЗ рд░реЛрдХреЗрдВрдЧреЗ рдпрд╛ рдпрджрд┐ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдЙрдкрдпреЛрдЧ рдХрд╛ рдорд╛рдорд▓рд╛ рдерд╛ рдЬрд╣рд╛рдВ рдпрд╣ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!

рдореЗрд░рд╛ рдкрд╣рд▓рд╛ рд╡рд┐рдЪрд╛рд░ @rpkilby рдХреЗ рдмрд┐рдВрджреБ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕рддреНрдпрд╛рдкрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИред рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рд╕реНрдХреАрдорд╛-рдХрдо рдЕрдЪреНрдЫрд╛ рд╣реИ - рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕реЗ рд╕реАрдзреЗ рдкрддрд╛ рдХрд░рдиреЗ рдпреЛрдЧреНрдп URL рд╕реЗ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рдЖрдЗрдП рдЗрд╕реЗ рдЕрднреА рдХреЗ рд▓рд┐рдП рдЦреБрд▓рд╛ рд░рдЦреЗрдВред рдореИрдВ рдЗрд╕реЗ рдПрдХ рд▓реЛрдХрдкреНрд░рд┐рдп рдЕрдиреБрд░реЛрдз рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВред (рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ _"рдХреЗ рд╕реНрддрд░ рдкрд░ рд╕рдВрдмреЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ MethodFilter "_ рдбреЙрдХреНрд╕ рдореЗрдВ рд╕рд╛рд░реНрдердХ рд╣реЛрдЧрд╛ред)

рдореИрдВ рдЬрд┐рд╕ рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЙрд╕рдХреЗ рд▓рд┐рдП рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдиреВрдВрдЧрд╛ рдХрд┐ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдХреНрд░реЗрдЯрд░ рдХреЗ рдбреЗрдЯрд╛ рдХреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╡рд╣рд╛рдВ рдХреЛрдИ рдХреБрдВрдЬреА рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдвреВрдВрдв рд░рд╣рд╛ рд╣реВрдВ рддреЛ рдореИрдВ рдЙрд╕рд╕реЗ рдкреВрдЫрддрд╛рдЫ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ... рдХрд╛рдпрд░рддрд╛ рдХреА рддрд░рд╣ред рдЖрдк рдХреНрд░реЗрдЯрд░ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдкреАрдЖрдИ рдкреНрд░рджрд╛рди рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдк рдирд╣реАрдВ рдЬрд╛рдирддреЗ рдХрд┐ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЬрд╛ рд░рд╣реЗ рдбреЗрдЯрд╛ рдореЗрдВ рдХреНрдпрд╛ рд╣реИ? рдХреНрдпрд╛ рдЖрдкрдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдХреБрдЫ рд░рд┐рдХреЙрд░реНрдб рдореЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╕реНрдХреАрдорд╛ рдХреЗ рдЧреБрдг рдЧрд╛рдпрдм рд╣реЛрдВрдЧреЗ, рдпрд╛ рдпрд╣ рдХрд┐ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░рд┐рдХреЙрд░реНрдб рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдордирдорд╛рдиреА рд╣реИрдВ?

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

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ JSONFilter рдХреЛ jsonfield__a_random_key=value рдЬреИрд╕реЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдирд╛ рд╡рд╛рдХрдИ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд╣реЛрдЧрд╛ред рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕реЗ objects.filter рд╡рд┐рдзрд┐ рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╢рд╛рдпрдж рдЯреНрд░реЗрдбрдСрдлрд╝ рдлрд╝рд┐рд▓реНрдЯрд░ рд╕рддреНрдпрд╛рдкрди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?

Q рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ QuerySet рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рд▓рд┐рдП 'рдкреНрд░рд╛рдХреГрддрд┐рдХ' рдХреНрд╡реЗрд░реА рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЕрднреА рдкреВрд░рд╛ рдХрд┐рдпрд╛ рд╣реИред рдпрд╣ рдПрдХ JsonField рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ ~ 1000 рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд╕рд╛рде рдХреНрд╡реЗрд░реАрд╕реЗрдЯ рдХреЗ рдЦрд┐рд▓рд╛рдл рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдпрд╣рд╛рдВ рд╣реИ:
https://github.com/shallquist/DJangoQuerySetFilter/blob/master/queryparser.py

рдЕрд░реЗ @shallquist рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ django-filter рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ QuerySetFilter рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВред рдХреНрдпрд╛ рдЖрдкрдиреЗ рдХрд╣реАрдВ рдЙрдкрдпреЛрдЧ рджрд╕реНрддрд╛рд╡реЗрдЬ рдХрд┐рдпрд╛ рдерд╛?

рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ рдЬреИрд╕рд╛ рдХрд┐ рдЬреАрдердм рдкрд░ рд░реАрдбрдореА рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрд░реНрдерд╛рддред
QuerySetFilter('рджреЛрд╕реНрддреЛрдВ').get_Query((person__address__city = Denver | person__address__city = рдмреЛрд▓реНрдбрд░) рдФрд░ рд╡реНрдпрдХреНрддрд┐__address_state ~= CO)
рдЬреЛ рдбреЗрд╡рд░ рдпрд╛ рдмреЛрд▓реНрдбрд░ рдХреЛрд▓реЛрд░рд╛рдбреЛ рдореЗрдВ рд░рд╣рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рджреЛрд╕реНрддреЛрдВ рдХреЛ рдкреБрдирдГ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд╡реЗрд░реА рддреИрдпрд╛рд░ рдХрд░реЗрдЧрд╛, рдЬрд╣рд╛рдВ рджреЛрд╕реНрдд рдПрдХ рдЬреЗрд╕рдирдлреАрд▓реНрдб рд╣реИред

BTW рдЗрд╕рдХрд╛ рдЕрдзрд┐рдХ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЪреВрдВрдХрд┐ Django рдлрд╝рд┐рд▓реНрдЯрд░ рдПрдореНрдмреЗрдбреЗрдб рд╕рд░рдгреА рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдХреНрд╡реЗрд░реА рдХрд░рдиреЗ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рд╣реИред

https://github.com/carltongibson/django-filter/issues/426#issuecomment -380224133

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ JSONFilter рдХреЛ jsonfield__a_random_key=value рдЬреИрд╕реЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдирд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд╣реЛрдЧрд╛ред рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕реЗ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдлрд╝рд┐рд▓реНрдЯрд░ рд╡рд┐рдзрд┐ред рд╢рд╛рдпрдж рдЯреНрд░реЗрдбрдСрдлрд╝ рдлрд╝рд┐рд▓реНрдЯрд░ рд╕рддреНрдпрд╛рдкрди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?

рдЕрд░реЗ @carltongibson , @rpkilby рдореИрдВ рдЗрд╕ рдкрд░ рдЖрдкрдХреЗ рд╡рд┐рдЪрд╛рд░ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдорд╛рди рд▓реЗрдВ рдХрд┐ my_field рдПрдХ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрд╕ JSONField рд╣реИ, рдФрд░ рдореИрдВ рдпрд╣ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ:

  • my_field__etc=value рдХреЗ рдЖрдХрд╛рд░ рдореЗрдВ рдПрдХ рдЖрд░рдИрдПрд╕рдЯреА рдлрд╝рд┐рд▓реНрдЯрд░ рдЬреЛрдбрд╝реЗрдВ рдЬрд╣рд╛рдВ etc JSONField рдФрд░ value рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдХреЛрдИ рднреА рдкреНрд░рд╢реНрди рд╣реИ рдЬреЛ рдЖрд░рдИрдПрд╕рдЯреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
  • рдлрд┐рд░ рдореИрдВ $#$8 MyModel.objects.filter(my_field__etc=value) #$ рдХреЗ рд░реВрдк рдореЗрдВ рдореЙрдбрд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рдореИрдиреЗрдЬрд░ рдХреЛ etc рдФрд░ value рдкрд╛рд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
  • рдЕрдВрдд рдореЗрдВ рдлрд╝рд┐рд▓реНрдЯрд░ рдЬреЛ рдХреБрдЫ рднреА рд▓реМрдЯрд╛рддрд╛ рд╣реИ рдЙрд╕реЗ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рдпрд╣ рд╕реБрдкрд░ рддреБрдЪреНрдЫ рдЬреИрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЗрд╕ рддрд░рд╣ рдХреБрдЫ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИред рдЕрдЧрд░ рдЖрдк рд▓реЛрдЧ рдореБрдЭреЗ рдХреБрдЫ рд╕реБрд░рд╛рдЧ рджреЗрдВ рддреЛ рдореИрдВ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред

рдХрд┐рд╕реА рднреА рд╡рд┐рдЪрд╛рд░ рдХреА рдЕрддреНрдпрдзрд┐рдХ рд╕рд░рд╛рд╣рдирд╛ рдХреА рдЬрд╛рдПрдЧреА!

рдХреНрдпрд╛ рдирд┐рдореНрди рдЬреИрд╕рд╛ рдХреБрдЫ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ?

class MyFilter(FilterSet):
    my_field__etc = filters.NumberFilter(field_name='my_field', lookup_expr='etc')

рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, field_name рдХреЛ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдореЙрдбрд▓ рдлрд╝реАрд▓реНрдб рдирд╛рдо рд╕реЗ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрдмрдХрд┐ рдЯреНрд░рд╛рдВрд╕рдлрд╝реЙрд░реНрдо рдФрд░ рд▓реБрдХрдЕрдк (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкрд░рд┐рд╡рд░реНрддрди) рдХреЛ lookup_expr рдореЗрдВ рд╕рдорд╛рд╣рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

@rpkilby рдЗрддрдиреА рддреНрд╡рд░рд┐рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж - рд╣рд╛рдБ рдмрд┐рд▓реНрдХреБрд▓, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЕрдиреБрд░реЛрдз рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ etc рдЪрд╛рд╣рд┐рдП ... рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рдлрд╝рд┐рд▓реНрдЯрд░ рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рд╛рд░реНрдбрдХреЛрдб рдирд╣реАрдВ рдХрд░ рд╕рдХрд╛

рдлрд╝рд┐рд▓реНрдЯрд░ рдЕрдзрд┐рдХ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:

class MyFilter(FilterSet):
    my_field = JSONFieldFilter(field_name='my_field')

рддреЛ, ?my_field__etc=value рдЬреИрд╕реЗ рдордирдорд╛рдиреЗ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ JSON рдлрд╝рд┐рд▓реНрдЯрд░ред

рдореБрдЭреЗ рджреЛ рд╕рдорд╕реНрдпрд╛рдПрдВ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, django-filter рдХреЗ рдореВрд▓реНрдп рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдо рдХреЛ рдорд╛рдиреНрдп рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ JSONField s рдореЗрдВ рдХреЛрдИ рд╕реНрдХреАрдорд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдРрд╕реЗ рдлрд╝рд┐рд▓реНрдЯрд░ рдЬреЗрдирд░реЗрдЯ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдЗрдирдмрд╛рдЙрдВрдб рдбреЗрдЯрд╛ рдХреЛ рдЙрдЪрд┐рдд рд░реВрдк рд╕реЗ рдорд╛рдиреНрдп рдХрд░рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдкрдХреЗ JSON рдлрд╝реАрд▓реНрдб рдореЗрдВ "рдЧрд┐рдирддреА" рдХреБрдВрдЬреА рд╣реИ, рддреЛ рдпрд╣ рд╕рдордЭрдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдХрд┐ рдХреЗрд╡рд▓ рд╕рдХрд╛рд░рд╛рддреНрдордХ рд╕рдВрдЦреНрдпрд╛рдПрдВ рд╣реА рдорд╛рдиреНрдп рд╣реИрдВред рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдЬреЛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рд╡рд╣ рдЧрд╛рд░рдВрдЯреА рд╣реИ рдХрд┐ рдорд╛рди рд╡реИрдз JSON рд╣реИред рддреЛ рдкреНрд░рд╢реНрди рдХрдо рд╕реЗ рдХрдо рдорд╛рдиреНрдп рд╣реЛрдВрдЧреЗ, рд▓реЗрдХрд┐рди рд╕рдВрднрд╡рддрдГ рдирд┐рд░рд░реНрдердХ рд╣реЛрдВрдЧреЗ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, data__count__gt='cat' )ред

рджреВрд╕рд░рд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреА MultiWidget -рдЖрдзрд╛рд░рд┐рдд рдлрд╝рд┐рд▓реНрдЯрд░ рдЬреИрд╕реА рд╣реА рд╕реАрдорд╛рдПрдБ рд╣реЛрдВрдЧреАред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рд╕рд╣реА рдкрд░рдо рдирд╛рдореЛрдВ рдХреЗ рд▓рд┐рдП рд╕рддреНрдпрд╛рдкрди рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред рд▓реЗрдХрд┐рди рдЙрд╕рдореЗрдВ рдЧреЛрддрд╛ рд▓рдЧрд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣рд╛рдБ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореИрдВ рд╢рд╛рдпрдж рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реВрдБрдЧрд╛ред рдЬрд╝рд░реБрд░рдд рд╣реИ:

  • рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рд┐рд▓реНрдЯрд░ рд╡рд░реНрдЧ, рдЬрд┐рд╕реЗ рдПрдХрд╛рдзрд┐рдХ рдкреИрд░рд╛ рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛ рдЪрд╛рд╣рд┐рдП
  • JSON рдбреЗрдЯрд╛ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рдкрддреНрд░ рдлрд╝реАрд▓реНрдб
  • рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ my_field__* рдкреИрд░рд╛ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдЬреЗрдЯред
class JSONWidget(widgets.Textarea):
    """A widget that handles multiple parameters prefixed with the field name."""

    def value_from_datadict(self, data, files, name):
        prefix = f'{name}{LOOKUP_SEP}'

        # this is doing two things: 
        # - matches multiple params for the base field name
        # - in addition to returning the value, we also need the full parameter name
        #   for querying. otherwise, values will be filtered against the base `name`. 
        return {k: v for k, v in data.items() if k.startswith(prefix)}

    def get_context(self, name, value, attrs):
        # to support rendering the widget, you would need to generate subwidgets
        # similar to MultiWidget.get_context.
        pass

class JSONField(postgres.forms.JSONField):
    widget = JSONWidget

    def clean(self, value):
        # note that it's not possible to collect/reraise any validation errors under
        # their actual parameter names. `form.add_error` should be used here, however
        # the field class does not have access to the form instance. raising 
        # ValidationError({k: str(original_exc)}) also does not work. 

        # clean/convert each value
        return {k: super().clean(v) for k, v in value.items()}

class JSONFilter(filters.Filter):
    field_class = JSONField

    def filter(self, qs, value):
        if value in EMPTY_VALUES:
            return qs
        return qs.filter(**value)

рдореИрдВрдиреЗ рдЙрдкрд░реЛрдХреНрдд рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдореЛрдЯреЗ рддреМрд░ рдкрд░ рд╕рд╣реА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╕реАрдорд╛рдПрдБ рд╣реИрдВ:

  • рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛрдореИрдВ рдмрддрд╛ рд╕рдХрддрд╛ рд╣реВрдВ, рдкреНрд░рддрд┐-рдкрд░рдо ValidationError s рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕рдВрднрд╛рд▓рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ
  • рдЦрд░рд╛рдм рдУрдкрдирдПрдкреАрдЖрдИ/рдХреЛрд░рдПрдкреАрдЖрдИ рд╕реНрдХреАрдорд╛ рд╕рдорд░реНрдерди? рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдХреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛ред
  • djangorestframework-filters MultiWidget рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рдирд╣реАрдВ рд╣реИ ред рдпрд╣ рдлрд╝рд┐рд▓реНрдЯрд░/рд╡рд┐рдЬреЗрдЯ рдЙрдиреНрд╣реАрдВ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рд╕рдорд╛рди рдореБрджреНрджреЛрдВ рдореЗрдВ рдЪрд▓реЗрдЧрд╛ред

@rpkilby рдЗрд╕ рдЧрд╣рди рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рджред

рдпрджрд┐ рдЖрдкрдХреЗ JSON рдлрд╝реАрд▓реНрдб рдореЗрдВ "рдЧрд┐рдирддреА" рдХреБрдВрдЬреА рд╣реИ, рддреЛ рдпрд╣ рд╕рдордЭрдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдХрд┐ рдХреЗрд╡рд▓ рд╕рдХрд╛рд░рд╛рддреНрдордХ рд╕рдВрдЦреНрдпрд╛рдПрдВ рд╣реА рдорд╛рдиреНрдп рд╣реИрдВред

рдпрд╣ рдПрдХ рдорд╣рд╛рди рдмрд┐рдВрджреБ рд╣реИ, рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдХреНрд╡реЗрд░реА рдорд╛рди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдорд╛рдиреНрдп рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдмрд╣реБрдд рдЪреБрдиреМрддреАрдкреВрд░реНрдг рд╣реИ рдХреНрдпреЛрдВрдХрд┐ MyModel.objects.filter(data__count="1") MyModel.objects.filter(data__count=1) рдХреЗ рд╕рдорд╛рди рдирд╣реАрдВ рд▓реМрдЯрд╛рдПрдЧрд╛ред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдХрд╣рддреЗ рд╣реИрдВ, рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ рд╕реЗ рдорд╛рди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред

рдЗрд╕рд▓рд┐рдП рдХреНрд╡реЗрд░реА рд╡реИрд▓реНрдпреВ рдореЗрдВ рдЯрд╛рдЗрдк рдХреА рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдПрдореНрдмреЗрдб рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдЫреЛрдбрд╝рдХрд░, рдкреВрд░реНрдгрд╛рдВрдХ рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП ?data__count=1:int рдЬреИрд╕рд╛ рдХреБрдЫ рдХрд░рдирд╛ рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП ?data__count=1:str рдЖрджрд┐ рдХрд░рдирд╛ред рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣рд╛рдВ рд╕реБрдЭрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рдХреА рдЕрдиреБрд╢рдВрд╕рд╛ рдирд╣реАрдВ рдХреА рдЬрд╛рддреА рд╣реИред

рдЕрдм рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ рдХрд┐ рдлрд┐рд▓реНрдЯрд░ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рдЗрддрдирд╛ рдореВрд▓реНрдпрд╡рд╛рди рдХреНрдпреЛрдВ рд╣реИред рдлрд┐рд░ рднреА, рдореИрдВ рдЗрд╕реЗ рдЖрдкрдХреЗ рд╕реБрдЭрд╛рд╡ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реВрдБрдЧрд╛! рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рдзрдиреНрдпрд╡рд╛рдж

@rpkilby , рдореБрдЭреЗ рдПрдХ рд╕рдорд╛рди рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдореЗрд░реЗ рдкрд╛рд╕ рджреЛ рдХреЙрд▓рдо рдХреЗ рд╕рд╛рде рдЗрд╕ рддрд░рд╣ рдХреА рдПрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рддрд╛рд▓рд┐рдХрд╛ рд╣реИ

meta_structure of type jsonb (This column has info like key1 of type string, key2 of type integer)

рдореЗрд░реЗ рдкрд╛рд╕ config_data рдирд╛рдо рдХреА рдПрдХ рдФрд░ рдЯреЗрдмрд▓ рд╣реИ рдЬрд┐рд╕рдореЗрдВ 3 рдХреЙрд▓рдо рд╣реЛрдВрдЧреЗред

config_id -> Foreign key to config table
meta_info -> jsonb type

рдиреЛрдЯ: рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рддрд╛рд▓рд┐рдХрд╛рдПрдБ рд╕рдЯреАрдХ рддрд╛рд▓рд┐рдХрд╛рдПрдБ рдирд╣реАрдВ рд╣реИрдВред рд╡реЗ рд╕рдВрджреЗрд╢ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд┐рд░реНрдл рдкреНрд░рддрд┐рдирд┐рдзрд┐ рд╕рдВрд╕реНрдХрд░рдг рд╣реИрдВред

рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рдорд┐рд▓рд╛рди рдХреА рдЬрд╛рдВрдЪ рдХрд░рдХреЗ рд╕рд╣реЗрдЬрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдореЗрдЯрд╛_рдЗрдиреНрдлреЛ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдлрд╝реАрд▓реНрдб рдХреЛ рдорд╛рдиреНрдп рдХрд░рддрд╛ рд╣реВрдВред

рдЖрд╡рд╢реНрдпрдХрддрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ config_data рддрд╛рд▓рд┐рдХрд╛ рдХреЗ meta_info рдХреЙрд▓рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдЙрджрд╛. рдореЗрдЯрд╛_рдЗрдиреНрдлреЛ__рдХреА1='рдПрдмреАрд╕реА'ред (рдХреБрдВрдЬреА 1 рдХреБрдЫ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)

рдореИрдВ рдКрдкрд░ рджрд┐рдП рдЧрдП рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рдерд╛ рд▓реЗрдХрд┐рди рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ JSONFilter рдХреНрд▓рд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реВрдВ рдЬрд┐рд╕реЗ рдЖрдкрдиреЗ рдКрдкрд░ рдмрдирд╛рдпрд╛ рд╣реИред

рдЙрджрд╛.

class ConfigDataFilterSet(django_filters.FilterSet):
    meta_info = JSONFilter(field_name='meta_info')

pp = ConfigDataFilterSet(data={'meta_info__key1': 'abc'})

рдЕрдм, рдЕрдЧрд░ рдореИрдВ pp.qs рдпрд╛ pp.filter_queryset() рдЪрд▓рд╛рддрд╛ рд╣реВрдВ рддреЛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореЗрдЯрд╛_рдЗрдиреНрдлреЛ рдлрд╝реАрд▓реНрдб рдкрд░ рдлрд╝рд┐рд▓реНрдЯрд░ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ ConfigDataFilterSet рд╡рд░реНрдЧ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдлрд╝реАрд▓реНрдб рдирд╛рдо рдореЗрдЯрд╛_рдЗрдиреНрдлреЛ рд╣реИред рдХреНрдпрд╛ рдЖрдк рдЗрд╕ рдмрд╛рдзрд╛ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдореЗрдВ рдореЗрд░реА рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

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

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

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

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

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

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

Alexx-G picture Alexx-G  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ