python - 尝试使用 createview 保存时出现 NOT NULL 约束失败错误
问题描述
这是我在 SO 上的第一篇文章,所以如果我错过了任何重要的细节,请告诉我。我正在对基于 dJango 的本土票务系统进行更新。
我有两个“父”模型(ParentProjects 和 Projects),它们捕获有关我们要跟踪的工作的详细信息。两种模型都有许多列,用于在关联表中存储信息以及一些 FK 关系。
通用的基于类的详细视图用于查看 Project 表中的对象,而 ParentProject 表由基于函数的视图访问。基于函数的视图完成加载父项目对象值的任务,就像基于类的详细视图对项目对象所做的一样。
我遇到的问题是我无法向自动插入父项目 ID 的 IDTasks 模型添加新条目。我可以通过手动选择我希望将 IDTask 关联到的父级,从管理站点(或者如果我在模型表单中启用“父级”字段,则从“客户端”站点)添加一个新的 IDTask。我还可以从父项目详细信息视图中编辑和保存现有 IDTask,而不会出现任何问题。但是,当我尝试使用 createview 添加 IDTask 时,dJango 报告 Not NULL 约束错误并且新条目未保存。
除了查看和尝试解决此问题的许多其他解决方案外,我还禁用了自动添加登录用户 ID 的代码,但仍然遇到相同的空约束错误。奇怪的是,我使用相同的基本 createview 结构将 FK 对象添加到 Projects 模型中,并且效果很好。我仍然对 Django 基于类的视图感到满意,所以肯定会遗漏一些明显的东西。
谢谢您的帮助!
以下是与我的问题相关的主要观点:
# Detail view for Parent Projects (function-based)
def ParentProjectDetail(request,parent_id):
parents = ParentProject.objects.get(id=parent_id)
projects = Project.objects.filter(parent_project__pk=parent_id).order_by('project_phase', '-launch_date',)
return render(request, 'otis/parent_detail.html', context={'parents':parents, 'projects':projects })
# Detail View for Projects (class-based)
class ProjectDetailView(generic.DetailView):
model = Project
context_object_name = 'project'
template_name = 'otis/project_detail.html'
# Add parent progress report
class add_idtask_view(SuccessMessageMixin, CreateView):
model = IDTasks
template_name = 'otis/id_report_form.html'
form_class = idTaskForm
success_message = "Report added"
def form_valid(self, form):
idtaskform = form.save(commit=False)
idtaskform.user = self.request.user
self.parents_id = self.kwargs.get('parent_id')
form.instance.ParentProject = get_object_or_404(ParentProject,id=self.parents_id)
return super(add_idtask_view, self).form_valid(form)
def get_success_url(self):
return reverse_lazy('otis:parent_detail', kwargs={'pk': self.parents_id})
这是模型形式:
class idTaskForm(ModelForm):
class Meta:
model = IDTasks
fields = ('parent_phase','complete','milestones','nextsteps','concerns')
widgets = {
'milestones': Textarea(attrs={'cols': 50, 'rows': 5, 'placeholder': 'Task details...'}),
'nextsteps': Textarea(attrs={'cols': 50, 'rows': 5, 'placeholder': 'Task details...'}),
'concerns': Textarea(attrs={'cols': 50, 'rows': 5, 'placeholder': 'Task details...'}),
}
labels = {
'parent_phase': mark_safe('<span class="required">Phase</span>'),
'complete': mark_safe('<span class="required">Percentage Complete</span>'),
'milestones': ('Milestones'),
'nextsteps': ('Next steps'),
'concerns': ('Concerns'),
}
以下是正在访问的两个模型:
# Parent Project Model
class ParentProject(models.Model):
class Meta:
verbose_name = "parent project"
verbose_name_plural = "parent projects"
ordering = ['title']
title = models.CharField('Name', max_length=100, null=True, blank=False)
parent_group = models.ForeignKey(ProjectGroups, on_delete=models.CASCADE, blank=True, null=True)
parent_type = models.ForeignKey(ProjectTypes, on_delete=models.CASCADE, null=True, blank=False)
description = models.TextField('description', blank=True)
term_due = models.ForeignKey(Terms, on_delete=models.CASCADE, blank=True, null=True)
term_year_due = models.ForeignKey(Years, on_delete=models.CASCADE, blank=True, null=True)
launch_date = models.DateField('launch date', blank=True, null=True)
parent_phase = models.ForeignKey(SDLCPhases, on_delete=models.CASCADE, null=True, blank=False)
history = HistoricalRecords()
def __str__(self):
return str(self.title)
def get_absolute_url(self):
return reverse('otis:parent_detail', kwargs={'pk': self.pk})
# Reports Model
class IDTasks(models.Model):
class Meta:
verbose_name = "Parent task"
verbose_name_plural = "Parent tasks"
ordering = ['updated_on']
parent = models.ForeignKey(ParentProject, on_delete=models.CASCADE)
parent_phase = models.ForeignKey(SDLCPhases, on_delete=models.CASCADE, null=True, blank=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
complete = models.IntegerField('percentage complete', blank=True, null=True, default=0)
milestones = models.TextField('milestones', blank=True)
nextsteps = models.TextField('next steps', blank=True)
concerns = models.TextField('concerns', blank=True)
updated_on = models.DateTimeField(auto_now_add=True, null=True)
history = HistoricalRecords()
def __str__(self):
return str(self.complete)
以下是网址格式:
# url for the parent project detail view
path('parent_detail/<int:parent_id>/', views.ParentProjectDetail, name='parent_detail'),
# url for the create report accessed within the detail view
path('parent_detail/<int:parent_id>/add_id_report/', views.add_idtask_view.as_view(), name='add_id_report'),
最后是调用modelform的模板链接:
<a href="{% url 'otis:add_id_report' parents.id %}">link_title</a>
解决方案
我能够通过像这样重组视图来解决我最初的问题:
class add_idtask_view(SuccessMessageMixin, CreateView):
model = IDTasks
template_name = 'otis/id_report_form.html'
form_class = idTaskForm
success_message = "Report added"
def form_valid(self, form):
parents_pid = self.kwargs.get('parent_pid')
self.parent_id = parents_pid
form.instance.user = self.request.user
form.instance.parent_id = parents_pid
return super(add_idtask_view, self).form_valid(form)
def get_success_url(self):
return reverse_lazy('otis:parent_detail', kwargs={'parent_pid': self.parent_id})
我做的第一件事是整理出我试图访问的表单字段和数据库字段。似乎我混淆了这些并且在我最初的观点中没有正确引用它们。
然而,一旦这些工作正常,我开始收到一个错误,指出视图需要一个整数但得到一个字符串。似乎,无论出于何种原因,当我使用 get_object_or_404 方法时,视图返回数据库对象的标题而不是主键。
推荐阅读
- android - 自定义 AppComponentFactory 无法实例化应用程序
- matlab - 周转时间:应该比交货时间低多少?
- sql-server - 关于在 SQL Server 中发送自动批量邮件的问题
- ruby-on-rails - 如何在 Rails 中创建动态命名空间或范围路由
- python - 使用字典将变量保存在文本文件中的问题
- python - Python:如何在另一个函数中使用一个函数返回的数据框
- c++ - 在 GitHub 上创建我的 C++ 库的发布版本的正确方法是什么?
- c# - 可以使用指针来修改只读字段吗?但为什么?
- azure-devops - Azure 工件 - 通用包 - 错误:尝试推送包时发生意外错误
- html - 如果我不知道文本是什么,如何使容器中的文本尽可能大?