这似乎应该是相当简单的东西,应该是一个常见的东西需要,但我尝试找到的答案越多,我得到的就越混乱。
我有一个事件模型链接到需要事件的多个其他模型,所以我为它创建了一个单独的事件模型。现在,我想在创建工作模型时创建一个事件,但我无法弄清楚如何去做。
在我的工作领域,我与一个事件有一个OneToOneField关系,而我在做事件时唯一需要决定的就是持续时间。
简化的工作模型可能如下所示:
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插入我的工作模型的事件字段,并将其全部提交到一个去。
我看了inlineformset_factory
,这似乎应该是我需要的东西,而且我一直在犯错,所以这是错误的想法,或者我使用它错了。我尝试了其他人建议的一些mixins,它们看起来有点矫枉过正,无论如何都不适合我。
答案 0 :(得分:2)
您可以为Event
创建第二个表单,并在模板中呈现它。然后在您的视图中,您可以先保存它,创建一个事件,然后保存您的Job
表单并将其相关事件设置为刚创建的事件。
或者(我可能会这样做),如果您更喜欢单一表单,则可以在工作表单中添加持续时间字段并覆盖表单{{1}功能。重写的保存可能看起来像这样
save
Formsets实际上是用于制作多个表单,所以在您使用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
的情况下(因此只创建需要单个表单来创建单个相关对象),使用它是没有意义的它们。
答案 1 :(得分:0)
我刚刚意识到我接受的答案并不完全正确。出于某种原因(django magic),save被多次调用,一次用于获取数据,一次用于保存,因此每次创建作业时都会生成两个事件实例。另一个问题是,在保存作业之前还必须保存事件,或者尝试运行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