def test_model_and_rows(): # Model only defaults to all() model, rows = model_and_rows(model=Foo, rows=None) assert model is Foo and str(rows.query) == str(Foo.objects.all().query) # rows is preserved and model is returned orig_rows = Foo.objects.filter(foo=2) model, rows = model_and_rows(model=None, rows=orig_rows) assert model is Foo and rows is orig_rows
def _from_model(cls, *, rows=None, model=None, filters, include=None, exclude=None): assert rows is None or isinstance(rows, QuerySet), \ 'auto__rows needs to be a QuerySet for filter generation to work. ' \ 'If it needs to be a lambda, provide a model with auto__model for filter generation, ' \ 'and pass the lambda as rows.' model, rows = model_and_rows(model, rows) assert model is not None or rows is not None, "auto__model or auto__rows must be specified" filters = cls.filters_from_model(model=model, include=include, exclude=exclude, filters=filters) return model, rows, filters
def __init__(self, *, model=None, rows=None, filters=None, _filters_dict=None, auto, **kwargs): assert isinstance(filters, dict) if auto: auto = QueryAutoConfig(**auto) auto_model, auto_rows, filters = self._from_model( model=auto.model, rows=auto.rows, filters=filters, include=auto.include, exclude=auto.exclude, ) assert model is None, "You can't use the auto feature and explicitly pass model. " \ "Either pass auto__model, or we will set the model for you from auto__rows" model = auto_model if rows is None: rows = auto_rows model, rows = model_and_rows(model, rows) setdefaults_path( kwargs, form__call_target=self.get_meta().form_class, ) self._form = None self.query_advanced_value = None self.query_error = None super(Query, self).__init__(model=model, rows=rows, **kwargs) collect_members(self, name='filters', items=filters, items_dict=_filters_dict, cls=self.get_meta().member_class) field_class = self.get_meta().form_class.get_meta().member_class declared_fields = Struct() declared_fields[FREETEXT_SEARCH_NAME] = field_class( _name=FREETEXT_SEARCH_NAME, display_name='Search', required=False, include=False, ) for name, filter in items(declared_members(self).filters): if filter.attr is None and getattr(filter.value_to_q, 'iommi_needs_attr', False): continue field = setdefaults_path( Namespace(), filter.field, _name=name, model_field=filter.model_field, attr=name if filter.attr is MISSING else filter.attr, call_target__cls=field_class, ) declared_fields[name] = field() # noinspection PyCallingNonCallable self.form: Form = self.form( _name='form', _fields_dict=declared_fields, attrs__method='get', actions__submit__attrs__value='Filter', ) declared_members(self).form = self.form self.advanced_simple_toggle = Action( attrs__href='#', attrs__class__iommi_query_toggle_simple_mode=True, attrs={'data-advanced-mode': 'simple'}, display_name='Switch to advanced search', ) self.form_container = self.form_container() # Filters need to be at the end to not steal the short names set_declared_member(self, 'filters', declared_members(self).pop('filters'))
def __init__(self, *, model=None, rows=None, filters=None, _filters_dict=None, auto=None, **kwargs): assert isinstance(filters, dict) if auto: auto = QueryAutoConfig(**auto) auto_model, auto_rows, filters = self._from_model( model=auto.model, rows=auto.rows, filters=filters, include=auto.include, exclude=auto.exclude, ) assert model is None, "You can't use the auto feature and explicitly pass model. " \ "Either pass auto__model, or we will set the model for you from auto__rows" model = auto_model if rows is None: rows = auto_rows model, rows = model_and_rows(model, rows) setdefaults_path( kwargs, form__call_target=self.get_meta().form_class, ) self.query_advanced_value = None self.query_error = None # Here we need to remove the freetext config from kwargs because we want to # handle it differently from the other fields. # BUT It's not safe to modify kwargs deeply! Because reinvoke() is evil: # It will call init again with the same kwargs + whatever additional kwargs # might have come from a parent or styling info. freetext_config = kwargs.get('form', {}).get('fields', {}).get('freetext', {}) if 'form' in kwargs and 'fields' in kwargs[ 'form'] and 'freetext' in kwargs['form']['fields']: # copy (just) the namespace so we can safely remove freetext from it kwargs = Namespace(flatten(Namespace(kwargs))) freetext_config = kwargs.get('form', {}).get('fields', {}).pop('freetext', {}) super(Query, self).__init__(model=model, rows=rows, **kwargs) collect_members(self, name='filters', items=filters, items_dict=_filters_dict, cls=self.get_meta().member_class) field_class = self.get_meta().form_class.get_meta().member_class declared_fields = Struct() declared_fields[FREETEXT_SEARCH_NAME] = field_class( _name=FREETEXT_SEARCH_NAME, display_name=gettext('Search'), required=False, include=False, help__include=False, **freetext_config) for name, filter in items(declared_members(self).filters): field = setdefaults_path( Namespace(), filter.field, _name=name, model_field=filter.model_field, attr=name if filter.attr is MISSING else filter.attr, call_target__cls=field_class, help__include=False, ) declared_fields[name] = field() # noinspection PyCallingNonCallable self.form: Form = self.form( _name='form', _fields_dict=declared_fields, attrs__method='get', actions__submit=dict( attrs={'data-iommi-filter-button': ''}, display_name=gettext('Filter'), ), ) declared_members(self).form = self.form self.advanced = declared_members(self).advanced = self.advanced( _name='advanced') self.form_container = self.form_container(_name='form_container') # Filters need to be at the end to not steal the short names set_declared_member(self, 'filters', declared_members(self).pop('filters'))