2012-04-09 21 views
7

Tôi mới dùng django, và như một ứng dụng học tập, tôi đang xây dựng một ứng dụng ghi nhật ký chi phí.Sao chép các trường ManyToMany từ một trường hợp mẫu khác

Trong mô hình của tôi, tôi có ba lớp giống như thế này (tôi đơn giản hóa chúng một chút cho ngắn gọn):

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 chỉ là một mẫu: khi hệ thống nhận ra rằng thời gian để chèn một chi phí định kỳ (ví dụ: tiền thuê nhà) cần lấy thông tin trong mẫu và sao chép chúng trong một trường hợp mới của lớp Expense. Dưới đây là các bit có liên quan từ RecurringExpense phương pháp chịu trách nhiệm về công việc:

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

Các công trình trên một cách hoàn hảo, nhưng nếu tôi bỏ ghi chú dòng tags=self.tags, django phàn nàn và ném các lỗi sau:

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 

tôi biết I could create a loop để giải quyết vấn đề này, nhưng tôi tự hỏi nếu có một cách thanh lịch hơn sẽ cho phép tôi thực hiện cùng một lúc ...

Trả lời

8

Phương pháp đơn giản nhất tôi có thể đưa ra:

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

Bạn cũng có thể thay thế 'Chi phí (...) '/'e.save()' bằng 'Expense.objects.create (...)' –

+0

Điều này có thể không hoạt động nếu bạn có một số lượng lớn thẻ (trình điều khiển SQL phụ thuộc). Trong trường hợp này, bạn có thể lặp trong các khối lớn trên tất cả các thẻ để thêm chúng. – odedfos

11

Bạn không thể đặt trường m2m trực tiếp như thế khi tạo mô hình i nstance. Hãy thử các cách sau để thay thế:

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

Bạn có thể kiểm tra https://docs.djangoproject.com/en/1.4/topics/db/examples/many_to_many/ để biết thêm ví dụ về cách làm việc với nhiều mối quan hệ.

+0

Hi và cảm ơn bạn đã trả lời của bạn. Có một lý do cụ thể tại sao bạn sử dụng phương thức '.add()' kết hợp với việc giải nén danh sách, chứ không phải là một phép gán đơn giản (xem câu trả lời của riêng tôi) không? – mac

+0

Tôi thường không cần phải thay thế bộ quan hệ m2m hiện có, chỉ cần thêm vào nó, vì vậy nhiều hơn được sử dụng để điều đó. Đối với trường hợp sử dụng của bạn, việc gán thực sự đơn giản hơn và sẽ hoạt động tốt, vì 'ManyRelatedObjectsDescriptor' thực hiện' .clear' + '.add (* values)' đằng sau hậu trường khi bạn thực hiện một phép gán. –

+0

Điểm tốt. Đã bỏ phiếu! :) – mac

Các vấn đề liên quan