def member_from_model(cls, model, factory_lookup, defaults_factory, factory_lookup_register_function=None, model_field_name=None, model_field=None, **kwargs): if model_field is None: assert model_field_name is not None, "Field can't be automatically created from model, you must specify it manually" sub_field_name, _, field_path_rest = model_field_name.partition('__') # noinspection PyProtectedMember model_field = get_field(model, sub_field_name) if field_path_rest: result = member_from_model( cls=cls, model=model_field.remote_field.model, factory_lookup=factory_lookup, defaults_factory=defaults_factory, factory_lookup_register_function=factory_lookup_register_function, model_field_name=field_path_rest, **kwargs) set_and_remember_for_reinvoke(result, attr=model_field_name) return result factory = factory_lookup.get(type(model_field), MISSING) if factory is MISSING: for django_field_type, foo in reversed(list(factory_lookup.items())): if isinstance(model_field, django_field_type): factory = foo break # pragma: no mutate optimization if factory is MISSING: message = f'No factory for {type(model_field).__name__}.' if factory_lookup_register_function is not None: message += ' Register a factory with register_factory or %s, you can also register one that returns None to not handle this field type' % factory_lookup_register_function.__name__ raise AssertionError(message) if factory is None: return None # Not strict evaluate on purpose factory = evaluate(factory, __match_empty=False, model_field=model_field, model_field_name=model_field_name) setdefaults_path( kwargs, _name=model_field_name, call_target__cls=cls, ) defaults = defaults_factory(model_field) if isinstance(factory, Namespace): factory = setdefaults_path( Namespace(), factory, defaults, ) else: kwargs.update(**defaults) return factory(model_field=model_field, model_field_name=model_field_name, model=model, **kwargs)
def test_set_and_remember_for_reinvoke(): x = MyReinvokable(foo=17) assert x._iommi_saved_params == dict(foo=17) assert x.kwargs.foo == 17 set_and_remember_for_reinvoke(x, foo=42) assert x.foo == 42 x = reinvoke(x, dict(bar=42)) assert x.kwargs == dict(foo=42, bar=42)
def on_bind(self) -> None: bind_members(self, name='filters') request = self.get_request() self.query_advanced_value = request_data(request).get( self.get_advanced_query_param(), '') if request else '' # TODO: should it be possible to have freetext as a callable? this code just treats callables as truthy if any(f.freetext for f in values(declared_members(self)['filters'])): set_and_remember_for_reinvoke(declared_members( self.form).fields[FREETEXT_SEARCH_NAME], include=True) declared_fields = declared_members(self.form)['fields'] for name, filter in items(self.filters): is_valid, message = filter.is_valid_filter(name=name, filter=filter) assert is_valid, message if name in declared_fields: field = setdefaults_path( Namespace(), _name=name, attr=name if filter.attr is MISSING else filter.attr, model_field=filter.model_field, help__include=False, ) declared_fields[name] = reinvoke(declared_fields[name], field) set_declared_member(self.form, 'fields', declared_fields) # Remove fields from the form that correspond to non-included filters declared_filters = declared_members(self)['filters'] for name, field in items(declared_fields): if name == FREETEXT_SEARCH_NAME: continue # We need to check if it's in declared_filters first, otherwise we remove any injected fields if name in declared_filters and name not in self.filters: set_and_remember_for_reinvoke(field, include=False) bind_members(self, name='endpoints') self.form = self.form.bind(parent=self) self._bound_members.form = self.form self.advanced = self._bound_members.advanced = self.advanced.bind( parent=self) self.form_container = self.form_container.bind(parent=self) self.filter_name_by_query_name = { x.query_name: name for name, x in items(self.filters) }