[英]django - Using one form to create two model instances
這似乎應該很簡單,並且應該是常見的事情,但是我嘗試找到答案的次數越多,我就越困惑。
我有一個事件模型,該模型鏈接到需要事件的多個其他模型,因此為它創建了一個單獨的事件模型。 現在,我想在創建工作模型時創建一個事件,但是我很難弄清楚該如何做。
在我的工作領域中,我與一個事件具有OneToOneField關系,而在制作事件時我唯一需要確定的就是持續時間。
簡化的Job模型可能如下所示:
class Job(models.Model):
customer = models.ForeignKey(Customer)
address = models.CharField(max_length=100, verbose_name="Job Address", null=False, blank=False)
city = models.CharField(max_length=100, verbose_name="City", null=True, blank=True)
state = models.CharField(max_length=2, verbose_name="State", null=True, blank=True)
zip = models.CharField(max_length=5, verbose_name="Zip Code", null=True, blank=True)
# Simply need to set duration
event = models.OneToOneField(Event, on_delete=models.CASCADE, null=False, blank=False)
簡化的事件模型可能如下所示:
class Event(models.Model):
TIME_LIST = (
(1, "0:30"),
(2, "1:00"),
(3, "1:30"),
(4, "2:00"),
(5, "2:30"),
(6, "3:00"),
(7, "3:30"),
(8, "4:00"),
(9, "4:30"),
(10, "5:00"),
(11, "5:30"),
(12, "6:00"),
(13, "6:30"),
(14, "7:00"),
(15, "7:30"),
(16, "8:00"),
)
title = models.CharField(max_length=255)
employee = models.ForeignKey(Employee, null=True, blank=True)
start_time = models.DateTimeField(null=True, blank=True)
end_time = models.DateTimeField(null=True, blank=True)
range = RecurrenceField(null=True, blank=True)
duration = models.IntegerField(choices=TIME_LIST, null=True, blank=True)
is_all_day = models.BooleanField(default=False, null=False, blank=False)
我正在使用通用CBV,因此很簡單:
class JobCreate(CreateView):
template_name = 'jobs/create.html'
success_url = '/schedule/add/'
form_class = JobCreateForm
def get_success_url(self):
return self.success_url + str(self.object.id)
我的表格可以是:
class JobCreateForm(forms.ModelForm):
class Meta:
model = Job
fields = [
'customer',
'address',
'city',
'state',
'zip',
]
我需要的是一種方法,可以在工作表格中的持續時間中選擇一個框,然后創建Event的新實例,將event_id插入Job模型的event字段中,然后一次性提交所有內容。
我查看了inlineformset_factory
,它似乎應該是我所需要的,並且不斷出錯,因此這是錯誤的主意,或者我使用的是錯誤的。 我嘗試了其他人建議的幾個混合器,它們看起來像是過分殺了,無論如何對我沒有用。
您可以為Event
創建第二個表單並將其呈現在模板中。 然后,在您的視圖中,您可以先保存它,創建一個事件,然后保存您的Job
表單並將其相關事件設置為剛剛創建的事件。
另外(我可能會這樣做),如果您希望使用一個表單,則可以將工期字段添加到工作表單中並覆蓋表單的save
功能。 覆蓋的保存可能看起來像這樣
def save(self, commit=True):
e = Event.objects.create(duration=self.cleaned_data.get('duration'))
job = super().save(commit=False)
job.event = e
job.save()
return job
表單集實際上是用於創建多個表單的,因此在您的情況下,當您使用OneToOneField
(從而僅創建需要單個表單來創建單個相關對象的表單)時,就沒有意義了。
我只是意識到我接受的答案並不完全正確。 由於某種原因(django魔術),保存被多次調用,一次用於獲取數據,一次被保存,因此每次創建作業時它都會創建兩個事件實例。 另一個問題是在保存作業或嘗試運行job.save()之前也必須保存事件。 我通過使用以下代碼解決了這一問題。
def save(self, commit=True):
job = super(JobCreateForm, self).save(commit=False)
if commit:
event = Event(duration=self.cleaned_data.get('duration'), title=self.cleaned_data.get('customer'))
event.save()
job.event = event
job.save()
return job
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.