Django遍历所有m2m关系

时间:2014-07-28 07:47:05

标签: django django-models django-orm

我需要遍历模型实例的所有m2m关系并将它们复制到新的模型实例。

source_id=request.GET.get('source_id', 1)
obj = Artist.objects.create(title='New artist')
source_obj = Artist.objects.get(id=source_id)
if source_obj.galleries.count():
   obj.galleries = source_obj.galleries.all()
if source_obj.suggested_artists.count():
   obj.suggested_artists = source_obj.suggested_artists.all()

目前我正在这样做,但我想遍历所有m2m字段并将相关数据复制到obj

我想要类似的东西:

for m2m_rel in source_obj.m2m_relations:
    print geattr(source_obj, m2m_rel).count()
    print geattr(source_obj, m2m_rel).all()

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

您可以像这样访问m2m关系条目:

for field in source_obj._meta.many_to_many:
    source = getattr(source_obj, field.attname)
    for item in source.all():
        # do something with item...
        print repr(item)

如果您正在尝试克隆模型,可以使用通用的 clone_objects 函数,如下所示。该函数将克隆一个对象列表并返回一个新的克隆对象列表(带有新的ID'):

# import Python's copy library
import copy

def clone_objects(objects):
    """
    Generic model object cloner function.
    """
    def clone(obj):
        """Return an identical copy of the instance with a new ID."""
        if not obj.pk:
            raise ValueError('Instance must be saved before it can be cloned.')
        duplicate = copy.copy(obj)
        # Setting pk to None tricks Django into thinking this is a new object.
        duplicate.pk = None
        duplicate.save()
        # ... but the trick loses all ManyToMany relations.
        for field in obj._meta.many_to_many:
            source = getattr(obj, field.attname)
            destination = getattr(duplicate, field.attname)
            for item in source.all():
                destination.add(item)
        return duplicate

    if not hasattr(objects,'__iter__'):
        objects = [ objects ]

    objs = []
    for obj in objects:
        new_obj = clone(obj)
        new_obj.save()
        objs.append(new_obj)

    return objs

"克隆的主要部分"代码来自此代码段:Clone model mixin