python - Django - 同一表单上的多个自定义模型
问题描述
我正在使用 Django 2.1 和 PostgreSQL。我的问题是我正在尝试创建一个表单来同时编辑两个不同的模型。该模型与 FK 相关,我看到的每个示例都与用户和配置文件模型有关,但是我无法复制我真正需要的东西。
我的模型简化以显示有关它们的相关信息是:
# base model for Campaigns.
class CampaignBase(models.Model):
....
project = models.ForeignKey(Project, on_delete=models.CASCADE)
creation_date = models.DateTimeField(auto_now_add=True)
start_date = models.DateTimeField(null=True, blank=True)
end_date = models.DateTimeField(null=True, blank=True)
....
# define investment campaign made on a project.
class InvestmentCampaign(models.Model):
....
campaign = models.ForeignKey(CampaignBase, on_delete=models.CASCADE, null=True, blank=True)
description = models.CharField(
blank=True,
max_length=25000,
)
....
我要创建的表单是包含end_date
FKCampaignBase
和Description
.InvestmentCampaign
现在我有这个UpdateView
来编辑 InvestmentCampaign,我需要适应我的实际需求,也就是更新CampaignBase
模型:
class ProjectEditInvestmentCampaignView(LoginRequiredMixin, SuccessMessageMixin, generic.UpdateView):
template_name = 'webplatform/project_edit_investment_campaign.html'
model = InvestmentCampaign
form_class = CreateInvestmentCampaignForm
success_message = 'Investment campaign updated!'
def get_success_url(self):
return reverse_lazy('project-update-investment-campaign', args=(self.kwargs['project'], self.kwargs['pk']))
# Make the view only available for the users with current fields
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
# here you can make your custom validation for any particular user
if request.user != self.object.campaign.project.user:
raise PermissionDenied()
return super().dispatch(request, *args, **kwargs)
# Set field as current user
def form_valid(self, form):
campaign = InvestmentCampaign.objects.get(pk=self.kwargs['campaign'])
form.instance.campaign = campaign
form.instance.history_change_reason = 'Investment campaign updated'
return super(ProjectEditInvestmentCampaignView, self).form_valid(form)
def get_context_data(self, **kwargs):
project = Project.objects.get(pk=self.kwargs['project'])
context = super(ProjectEditInvestmentCampaignView, self).get_context_data(**kwargs)
context['project'] = project
return context
我的表格是:
class CreateCampaignBaseForm(forms.ModelForm):
class Meta:
model = CampaignBase
fields = ('end_date',)
widgets = {
'end_date': DateTimePickerInput(),
}
def __init__(self, *args, **kwargs):
# first call parent's constructor
super(CreateCampaignBaseForm, self).__init__(*args, **kwargs)
# evade all labels and help text to appear when using "as_crispy_tag"
self.helper = FormHelper(self)
self.helper.form_show_labels = False
self.helper._help_text_inline = True
class CreateInvestmentCampaignForm(forms.ModelForm):
class Meta:
model = InvestmentCampaign
fields = ('description')
widgets = {
'description': SummernoteWidget(attrs={'summernote': {
'placeholder': 'Add some details of the Investment Campaign here...'}}),
}
def __init__(self, *args, **kwargs):
# first call parent's constructor
super(CreateInvestmentCampaignForm, self).__init__(*args, **kwargs)
# evade all labels and help text to appear when using "as_crispy_tag"
self.helper = FormHelper(self)
self.helper.form_show_labels = False
self.helper._help_text_inline = True
我到处读到,最好的方法是使用基于函数的视图,并调用我拥有的每个表单,然后进行验证。问题是我不知道如何以两种形式使用正确的对象填充字段,而且我不知道如何执行与 get_context_data 等效的操作,也不知道如何获取self
与get_success_url
(因为对于基于函数的视图,我只有请求 attr,所以我无法访问 kwargs)。
我见过一些人使用django-betterforms,但同样,唯一的例子是 auth 和 profile 模型,我看不到用我自己的模型复制它的方法。
非常感谢。
解决方案
如果您只想更改 上的一个字段end_date
,BaseCampaign
那么您应该只使用一种表单。只需在您和您的方法中添加end_date
一个附加字段(例如forms.DateTimeField()
),保存表单后,在相关活动上设置值:CreateInvestmentCampaignForm
form.valid()
def form_valid(self, form):
inv_campaign = form.save(commit=False)
inv_campaign.campaign.end_date = form.cleaned_data['end_date']
inv_campaign.campaign.save()
inv_campaign.history_change_reason = ...
return super().form_valid(form)
以下是如何添加end_date
到您的表单并正确初始化它:
class CreateInvestmentCampaignForm(ModelForm):
end_date = forms.DateTimeField(blank=True)
class Meta:
model = InvestmentCampaign
fields = ('description')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.campaign:
self.fields['end_date'].initial = self.instance.campaign.end_date
推荐阅读
- c - 有符号整数溢出
- c# - 我的简单 Lockbits Image 类中有一个错误
- git - Git 推送到 Heroku 永远不会从写入和总计对象消息的步骤传递
- angular - NGXS Select Observable上的RxJS超时?
- python - 使用 pybind11 在 C++ 之间传递 Python 大整数(>256 位)
- r - 在R中的模式之间粘贴字符串
- python - 即使尝试除了代码块,错误也会不断出现
- data-structures - 绳索和自平衡二叉树混合?(即具有快速第 n 个元素查找的排序集)
- termux - 不要从 github 打开项目
- javascript - 来自更高层次的 jQuery 内容?