2012-04-09 99 views
7

我是django的新手,作为一个学习应用程序,我正在构建一个费用日志记录应用程序。将ManyToMany字段从一个模型实例复制到另一个

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

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解决这个问题,但我想知道是否有一个更优雅的方式,可以让我一次执行相同...

回答

8

我能想出的方法simpliest:

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

您也可以用'Expense.objects.create(...)'代替'Expense(...)'/'e.save()' – 2013-12-17 12:59:58

+0

如果您有大量标签(SQL驱动程序依赖)。在这种情况下,您可以在所有标签上大块地迭代以添加它们。 – odedfos 2014-03-17 09:10:21

11

您不能直接设置一个m2m字段,就像创建模型时一样nstance。而不是尝试以下操作:

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/关于如何与许多一对多关系的工作更多的例子。

+0

你好,感谢你的回答。为什么你使用'.add()'方法并结合列表的拆包,而不是简单的赋值(请参阅我自己的答案),是否有特定的原因? – mac 2012-04-10 17:33:18

+0

我经常不需要替换现有的m2m关系集,只需添加它即可,所以更习惯于此。对于你的用例,分配比较简单,应该可以正常工作,因为'ManyRelatedObjectsDescriptor'在你做后台任务时在后台执行'.clear' +'.add(* values)'。 – 2012-04-10 19:00:29

+0

好点。 Upvoted! :) – mac 2012-04-10 20:57:53

相关问题