我花了很多时间寻找我认为应该是Django中非常基本的功能的功能。但是我只是无法正常工作,
我找不到与django的m2m小部件功能相同的小部件,但是如果不存在,还将创建新的模型实例。
[注意:这里的模型实例已经存在,意味着在嵌入式窗口小部件中输入的数据已经存在于数据库中。
例如如果我有以下模型:
class Outcome(models.Model):
outcome = models.CharField(max_length=255)
outcome_short_name = models.CharField(max_length=10, blank=True, null=True)
class Course(models.Model):
course_title = models.CharField(
verbose_name=COURSE_SINGULAR + " title", max_length=200, unique=True
)
course_outcome = models.ManyToManyField(
Outcome, verbose_name=COURSE_SINGULAR + " outcome", blank=True
)
然后我希望在创建课程时将“结果”显示为该图像:Image of adding new course with inline outcomes
现在,如果用户添加的结果数据已经存在,则应仅将它们映射到课程。否则,它应该首先将结果存储到数据库中,然后将其映射到课程中。
任何正确方向的指导都将受到高度赞赏。
谢谢,
编辑:正如@dirkgroten建议使用modelformset一样,我将FormView更改为:
class CourseFormView(FormView):
template_name = "course/course_form.html"
form_class = CourseForm
success_url = "/admin/"
def get_context_data(self, **kwargs):
context = super(CourseFormView, self).get_context_data(**kwargs)
if self.request.POST:
context["outcomes"] = OutcomeFormSet(self.request.POST)
else:
context["outcomes"] = OutcomeFormSet(queryset=Outcome.objects.none())
return context
def form_valid(self, form, **kwargs):
super(CourseFormView, self).get_context_data(**kwargs)
context = self.get_context_data()
outcomes_formset = context["outcomes"]
if not outcomes_formset.is_valid():
return super().form_invalid(form)
cleaned_data = form.cleaned_data
cleaned_data.pop("course_outcome")
course = Course.objects.create(**cleaned_data)
course.save()
outcomes_formset.instance = course
outcomes_formset.save()
course.course_outcome.set(Outcome.objects.filter(course_outcome=course))
return super().form_valid(form)
一切看起来都很好,但是如果数据库中已经存在formset中的表单数据,那么我的model_formset不会经过验证。例如。如果我在表单集中输入(outcome =“ test_outcome”,result_short_name =“ test_short”)并且结果表中已经存在相同的数据,那么我的表单集会给出错误:具有该结果和结果简称的结果已经存在。
有什么办法可以解决这种情况,或者我做错了什么?
您可以在以下位置进行测试:http://code.gdy.club:8001/course/add/results_list:http://code.gdy.club:8001/outcome/
谢谢,
-苏拉杰https://hacksj4u.wordpress.comhttps://github.com/SurajDadral
您需要处理自己已经存在Outcome
的情况。验证表单时的默认设置是假定将创建一个新对象,因此,如果您将字段设置为unique_together
,则单个表单将不进行验证。
您可以像这样在OutcomeFormset
的clean()
方法上进行操作:
from django.core.exceptions import NON_FIELD_ERRORS
def clean(self):
cleaned_data = super().clean()
for i in range(0, self.total_form_count()):
form = self.forms[i]
if form.non_field_errors() and len(form.errors) == 1:
# the only error is probably due to unique_together constraint
try:
form.instance = Outcome.objects.get(outcome=form.data.get('outcome'), outcome_short_name=form.data.get('outcome_short_name'))
except Outcome.DoesNotExist:
pass # some other error
else:
del form._errors[NON_FIELD_ERRORS]
return cleaned_data
然后在您的视图中,保存表单集时,应遍历所有表单,而不是保存实例具有pk
的表单:
for form in outcomes_formset:
outcome = form.instance
if not outcome.pk:
outcome = form.save()
course.course_outcome.add(outcome)