def __init__(self, target: models.Field): default = self.NO_DEFAULT if target.has_default(): if isinstance(target.get_default(), Enum): default = target.get_default().value else: default = target.get_default() choices = None if target.choices: choices = [] for value, label in target.choices: choices.append(label) super().__init__(name=target.name, type=self.define_representation_type(target), description=target.help_text, default=default, is_required=self.check_is_required(target), choices=choices) if self.type is Attribute.TYPE.OBJECT: if isinstance(target, (models.OneToOneField, models.ForeignKey)): self.type_of = target.related_model else: raise NotImplementedError() if self.type is Attribute.TYPE.ARRAY: self.type_of = target.related_model if self.type is Attribute.TYPE.FILE: self.type = Attribute.TYPE.STRING self.target = target
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)
def _skip_field(self, field: Field) -> bool: from django.contrib.contenttypes.fields import GenericRelation # check for fill optional argument if isinstance(self.fill_in_optional, bool): field.fill_optional = self.fill_in_optional else: field.fill_optional = field.name in self.fill_in_optional if isinstance(field, FileField) and not self.create_files: return True # Don't Skip related _id fields defined in the iterator attributes if ((isinstance(field, OneToOneField) or isinstance(field, ForeignKey)) and hasattr(field, "attname") and field.attname in self.iterator_attrs): return False # Skip links to parent so parent is not created twice. if isinstance(field, OneToOneField) and self._remote_field(field).parent_link: return True if isinstance(field, (AutoField, GenericRelation, OrderWrt)): return True if all([ field.name not in self.model_attrs, field.name not in self.rel_fields, field.name not in self.attr_mapping, ]): # Django is quirky in that BooleanFields are always "blank", # but have no default. if not field.fill_optional and ( not issubclass(field.__class__, Field) or field.has_default() or (field.blank and not isinstance(field, BooleanField))): return True if field.name not in self.model_attrs: if field.name not in self.rel_fields and (field.null and not field.fill_optional): return True return False