def get_field_meta(self, field: models.Field) -> OrderedDict: # check if we need to override default get_field_meta behaviour get_field_meta = getattr(self, 'get_%s_field_meta' % field.name, None) if callable(get_field_meta): return get_field_meta(field, self.obj) sentinel = object() d = OrderedDict() for attr in self.attr_list: val = getattr(field, attr, sentinel) if val is sentinel: continue if attr in ['max_length']: if val is None: continue if attr in ['verbose_name']: val = force_text(val) d[attr] = val d['type'] = field.get_internal_type() d['required'] = self.is_required(field) if field.default != models.NOT_PROVIDED: if callable(field.default): d['default'] = field.default() else: d['default'] = field.default if hasattr(field, 'choices') and field.choices: d['choices'] = list(self.format_choices(field)) if field.related_model: if field.name not in self.no_data: user_url_getter = getattr(self, 'get_%s_dataset_url' % field.name.lower(), None) if callable(user_url_getter): d['data'] = user_url_getter(field, self.obj) elif field.name in self.dataset_urls: d['data'] = force_text(self.dataset_urls[field.name]) else: d['data'] = self.get_field_related_data(field) data_update = self.update_fields.get(field.name, {}) d.update(data_update) # check if we need to perform runtime update update_field_meta_callback = getattr(self, 'update_%s_field_meta' % field.name, None) if callable(update_field_meta_callback): d.update(update_field_meta_callback(field, self.obj)) return d
def generate_value(self, field: Field, commit: bool = True) -> Any: """Call the associated generator with a field passing all required args. Generator Resolution Precedence Order: -- `field.default` - model field default value, unless explicitly overwritten during baking -- `attr_mapping` - mapping per attribute name -- `choices` -- mapping from available field choices -- `type_mapping` - mapping from user defined type associated generators -- `default_mapping` - mapping from pre-defined type associated generators `attr_mapping` and `type_mapping` can be defined easily overwriting the model. """ is_content_type_fk = isinstance(field, ForeignKey) and issubclass( self._remote_field(field).model, contenttypes.models.ContentType) # we only use default unless the field is overwritten in `self.rel_fields` if field.has_default() and field.name not in self.rel_fields: if callable(field.default): return field.default() return field.default elif field.name in self.attr_mapping: generator = self.attr_mapping[field.name] elif getattr(field, "choices"): generator = random_gen.gen_from_choices(field.choices) elif is_content_type_fk: generator = self.type_mapping[contenttypes.models.ContentType] elif generators.get(field.__class__): generator = generators.get(field.__class__) elif field.__class__ in self.type_mapping: generator = self.type_mapping[field.__class__] else: raise TypeError("%s is not supported by baker." % field.__class__) # attributes like max_length, decimal_places are taken into account when # generating the value. field._using = self._using generator_attrs = get_required_values(generator, field) if field.name in self.rel_fields: generator_attrs.update( filter_rel_attrs(field.name, **self.rel_attrs)) if not commit: generator = getattr(generator, "prepare", generator) return generator(**generator_attrs)