Search code examples
pythondjangodjango-modelsdjango-1.4

Copying ManyToMany fields from one model instance to another


I'm new to django, and as a learning app, I'm building an expense logging application.

In my models I have three classes that look like this (I simplified them slightly for brevity):

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 is just a template: when the system realises that the time to insert a recurring expense (e.g.: the rent) it should take the info in the template and copy them in a new instance of the Expense class. Here's the relevant bit from the RecurringExpense method in charge of the work:

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

The above works flawlessly, but if I uncomment the tags=self.tags line, django complains and throw the following error:

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 know I could create a loop to work around this problem, but I wonder if there is a more elegant way that would allow me to perform the same at once....


Solution

  • The simpliest method I could come up with:

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