2012-04-09 14 views
7

Soy nuevo en django y, como aplicación de aprendizaje, estoy creando una aplicación de registro de gastos.Copiar campos de ManyToMany de una instancia de modelo a otra

En mis modelos Tengo tres clases que se ven así (me simplificado ligeramente por razones de brevedad):

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 es simplemente una plantilla: cuando el sistema se da cuenta de que el tiempo para insertar un gasto recurrente (ej .: el alquiler) debe tomar la información en la plantilla y copiarla en una nueva instancia de la clase Expense. Aquí está la parte correspondiente del método RecurringExpense a cargo de la obra:

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

lo anterior funciona sin problemas, pero si lo elimine la línea tags=self.tags, Django se queja y lanzar el siguiente 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 sepa I could create a loop para evitar este problema, pero me pregunto si hay una manera más elegante que me permita realizar lo mismo a la vez ...

Respuesta

8

El método más simple que podía llegar a:

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

También puede reemplazar 'Expense (...)' /'e.save() 'con' Expense.objects.create (...) ' –

+0

Esto podría no funcionar si tiene una gran cantidad de etiquetas (controlador SQL) dependiente). En este caso, puede iterar en grandes porciones sobre todas las etiquetas para agregarlas. – odedfos

11

No puede establecer un campo m2m directamente así al crear un modelo i nstance. Intente lo siguiente en su lugar:

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

Puede comprobar https://docs.djangoproject.com/en/1.4/topics/db/examples/many_to_many/ para más ejemplos sobre cómo trabajar con las relaciones de muchos a muchos.

+0

Hola y gracias por su respuesta. ¿Existe alguna razón específica por la que use el método '.add()' en combinación con el desempaquetado de la lista, en lugar de una asignación simple (vea mi propia respuesta)? – mac

+0

A menudo no es necesario que reemplace el conjunto de relaciones m2m existente, simplemente agréguelo, por lo que estoy más acostumbrado a eso. Para su caso de uso, la asignación es más simple y debería funcionar bien, ya que 'ManyRelatedObjectsDescriptor' hace' .clear' + '.add (* values)' detrás de las escenas cuando realiza una tarea. –

+0

Buen punto. ¡Voto ascendente! :) – mac

Cuestiones relacionadas