django formsets验证错误(不接受空白字段)

时间:2017-07-02 13:44:07

标签: python django

我有两个以一对多关系连接的模型(Workout和ExerciseSet)。我试图使用CreateView来构建一个允许我同时创建锻炼和锻炼集的表单。事情是当我只有一个运动设置字段(在inlineformset_factory中额外= 1)时,它可以工作 - 但是当我想要设置额外的更大数字(如3)时,它只有在设置了所有锻炼时才有效。否则会引发null value in column "repetitions" violates not-null constraint错误。

我想在inlineformset类中覆盖clean方法来解决这个问题,但是当我调用super.clean()时,它会一直返回None。只是想知道是否有人可以提供帮助。

编辑 - 我建议在模型字段中包含blank = True和null = True。我可以通过将验证代码移动到表单来使其工作,但它似乎有点hackish。有没有更好的方法来进行验证?

models.py

class Workout(models.Model):
    profile = models.ForeignKey(
            'Profile', on_delete=models.CASCADE, blank=False
        )

class ExerciseSet(models.Model):
    EXERCISE_TYPE_CHOICES = (
        ('pushup', 'Push Up'),
        ('situp', 'Sit-up')
    )

    workout = models.ForeignKey(
            'Workout', on_delete=models.CASCADE, related_name='exercise_sets'
        )

    repetitions = models.PositiveIntegerField(blank=True, null=True)
    exercise_type = models.CharField(max_length=100, choices=EXERCISE_TYPE_CHOICES, blank=True, null=True)

forms.py

class WorkoutForm(ModelForm):
    class Meta:
        model = Workout
        exclude = ()

class ExerciseSetForm(ModelForm):
    class Meta:
        model = ExerciseSet
        exclude = ()

class CustomExerciseSetInlineFormSet(BaseInlineFormSet):
    def clean(self):
        cleaned_data = super().clean()
        print('custom')
        print(cleaned_data)


ExerciseSetFormSet = inlineformset_factory(Workout, ExerciseSet, form=ExerciseSetForm, 
    formset=CustomExerciseSetInlineFormSet, extra=3)

views.py

class WorkoutCreate(CreateView):
    model = Workout
    fields = ['profile', 'created']

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        template_name = 'pushup/workout_form.html'

        context['workout_form'] = WorkoutForm()
        context['exercise_set_form'] = ExerciseSetFormSet()

        return context

    def post(self, request, *args, **kwargs):
        workout_form = WorkoutForm(request.POST)
        formset = ExerciseSetFormSet(request.POST)

        if workout_form.is_valid() and formset.is_valid():
            with transaction.atomic():
                workouts_saved = 0
                workout = workout_form.save()

                for exercise_set_form in formset:
                    exercise_set = exercise_set_form.save(commit=False)

                    if exercise_set.repetitions == None or exercise_set.exercise_type == None:
                        continue

                    exercise_set.workout = workout
                    exercise_set.save()
                    workouts_saved += 1

                if workouts_saved == 0:
                    raise ValidationError('No workouts are valid')

                return HttpResponseRedirect(reverse_lazy('pushup:workout-detail', kwargs={'pk': workout.pk}))
        else:
            raise Http404 

0 个答案:

没有答案