【问题标题】:Copying ManyToMany fields from one model instance to another将 ManyToMany 字段从一个模型实例复制到另一个模型实例
【发布时间】:2012-04-09 18:39:49
【问题描述】:

我是 django 新手,作为一个学习应用程序,我正在构建一个费用记录应用程序。

在我的模型中,我有三个看起来像这样的类(为简洁起见,我稍微简化了它们):

class AbstractExpense(models.Model):
    description = models.CharField(max_length=100)
    amount      = models.IntegerField()
    category    = models.ForeignKey('Category')
    tags        = models.ManyToManyField('Tag')
    insert_date = models.DateTimeField(auto_now=True)

    class Meta(object):
        abstract = True

class Expense(AbstractExpense):
    date        = models.DateField('Date')

class RecurringExpense(AbstractExpense):
    FREQUENCY_CHOICES = (('D', 'daily'),
                         ('W', 'weekly'),
                         ('M', 'monthly'),
                         ('Y', 'yearly'))
    start_date = models.DateField(blank=False)
    end_date = models.DateField(blank=True, null=True)
    last_check = models.DateField(blank=True, null=True)
    frequency = models.CharField(blank=False, max_length=1, choices=FREQUENCY_CHOICES)

RecurringExpense 只是一个模板:当系统意识到需要插入经常性费用(例如:租金)时,它应该获取模板中的信息并将它们复制到 Expense 类的新实例中.以下是负责这项工作的RecurringExpense 方法的相关部分:

Expense(description=self.description,
        amount=self.amount,
        category=self.category,
        # tags=self.tags,
        date=expense_date).save()

上述工作完美无缺,但如果我取消注释 tags=self.tags 行,django 会抱怨并抛出以下错误:

Exception Type: TypeError
Exception Value: 'tags' is an invalid keyword argument for this function
Exception Location: <snip>/django/db/models/base.py in __init__, line 367

我知道I could create a loop 可以解决这个问题,但我想知道是否有更优雅的方法可以让我一次执行相同的操作....

【问题讨论】:

    标签: python django django-models django-1.4


    【解决方案1】:

    在创建模型实例时,您不能直接设置 m2m 字段。请尝试以下方法:

    expense = Expense(description=self.description,
            amount=self.amount,
            category=self.category,
            date=expense_date)
    expense.save()
    expense.tags.add(*self.tags.all())
    

    您可以查看https://docs.djangoproject.com/en/1.4/topics/db/examples/many_to_many/ 以获取有关如何处理多对多关系的更多示例。

    【讨论】:

    • 您好,感谢您的回答。您是否有特定原因将.add() 方法与列表的解包结合使用,而不是简单的分配(请参阅我自己的答案)?
    • 我经常不需要替换现有的m2m关系集,添加就行了,所以比较习惯了。对于您的用例,分配确实更简单,应该可以正常工作,就像 ManyRelatedObjectsDescriptor 在您进行分配时在幕后执行 .clear + .add(*values) 一样。
    • * 在这里做什么?我看到它可以与它一起使用,并且没有它就无法使用,但是我很难查看有关原因的文档...
    • @awidgery 这是 Python 的基本功能,请参阅docs.python.org/2/tutorial/… 将列表“解包”到函数参数中。
    【解决方案2】:

    我能想到的最简单的方法:

    e = Expense(description=self.description,
                amount=self.amount,
                category=self.category,
                date=expense_date)
    e.save()
    e.tags = self.tags.all()
    

    【讨论】:

    • 也可以将Expense(...)/e.save()替换为Expense.objects.create(...)
    • 如果您有大量标签(依赖于 SQL 驱动程序),这可能不起作用。在这种情况下,您可以对所有标签进行大块迭代以添加它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多