def get_verbose_name(model_or_queryset, field_path): if isinstance(model_or_queryset, Manager): model = model_or_queryset.model elif isinstance(model_or_queryset, QuerySet): model = model_or_queryset.model elif isinstance(model_or_queryset, Model): model = model_or_queryset else: raise AttributeError("`get_verbose_name` expects Manager, Queryset or Model as first parameter") if isinstance(field_path, basestring): field = get_field_by_path(model, field_path) elif isinstance(field_path, models.Field): field = field_path return field.verbose_name
def merge(master, other, fields=None, commit=False, m2m=None, related=None): # noqa """ Merge 'other' into master. `fields` is a list of fieldnames that must be readed from ``other`` to put into master. If ``fields`` is None ``master`` will get all the ``other`` values except primary_key. Finally ``other`` will be deleted and master will be preserved @param master: Model instance @param other: Model instance @param fields: list of fieldnames to merge @param m2m: list of m2m fields to merge. If empty will be removed @param related: list of related fieldnames to merge. If empty will be removed @return: """ fields = fields or [f.name for f in master._meta.fields] all_m2m = {} all_related = {} if related == ALL_FIELDS: related = [rel.get_accessor_name() for rel in compat.get_all_related_objects(master)] # for rel in master._meta.get_all_related_objects(False, False, False)] if m2m == ALL_FIELDS: m2m = [field.name for field in master._meta.many_to_many] if m2m and not commit: raise ValueError('Cannot save related with `commit=False`') with compat.atomic(): result = clone_instance(master) for fieldname in fields: f = get_field_by_path(master, fieldname) if f and not f.primary_key: setattr(result, fieldname, getattr(other, fieldname)) if m2m: for fieldname in set(m2m): all_m2m[fieldname] = [] field_object = get_field_by_path(master, fieldname) if not isinstance(field_object, ManyToManyField): raise ValueError('{0} is not a ManyToManyField field'.format(fieldname)) source_m2m = getattr(other, field_object.name) for r in source_m2m.all(): all_m2m[fieldname].append(r) if related: for name in set(related): related_object = get_field_by_path(master, name) all_related[name] = [] if related_object and isinstance(related_object.field, OneToOneField): try: accessor = getattr(other, name) all_related[name] = [(related_object.field.name, accessor)] except ObjectDoesNotExist: pass else: accessor = getattr(other, name, None) if accessor: rel_fieldname = list(accessor.core_filters.keys())[0].split('__')[0] for r in accessor.all(): all_related[name].append((rel_fieldname, r)) if commit: for name, elements in list(all_related.items()): for rel_fieldname, element in elements: setattr(element, rel_fieldname, master) element.save() other.delete() result.save() for fieldname, elements in list(all_m2m.items()): dest_m2m = getattr(result, fieldname) for element in elements: dest_m2m.add(element) return result