Django - 当视图中似乎存在错误时,如何调试 POST 的代码?

Django - How can I debug code which POST's when a bug seems to be in the view?

我想我会问一个宽泛的问题,这样我可以更好地了解 Django,并且可以更轻松地处理我可能遇到的任何类似问题。我遇到的具体问题是我已经编写了我的第一个表单集代码,它可以正确呈现表单,但是在发布时没有创建新对象。

我可以从服务器上看到表单已经发布,我没有收到任何错误,但是没有数据被添加到我的数据库中(从 django admin 和 manage.py shell 检查)。也许可以阅读 manage.py shell 中发布的内容?我希望能够检查表单是否正确发布了它的数据并且是否已被视图接收到。然后我就能明白为什么数据没有正确发布或者视图没有正确处理它。

对于具体问题,我会将我的代码放在下面,以防这是一个简单的初学者错误,你们中的一个向导可以发现。为了我自己的目的,我试图遵循和改编 this tutorial

Models.py

class Chunk(models.Model):
    name = models.CharField(max_length=250)
    text = models.CharField(max_length=500)
    images = models.FileField()
    question = models.CharField(max_length=250)
    expected_completion_time = models.IntegerField(default=1)
    keywords = models.CharField(max_length=250, blank=True, null=True)
    topic = models.CharField(max_length=250, blank=True, null=True)
    course = models.CharField(max_length=250, blank=True, null=True)
    is_flagged = models.BooleanField(default=False)

    def get_absolute_url(self):
        return reverse('detail', kwargs={'pk':self.pk})

    def __str__(self):
        return self.name


class Concept(Chunk):
    application = models.CharField(max_length=500)

    @property
    def mode(self):
        return "concept"


class Subconcepts(models.Model):
    subconcept = models.CharField(max_length=500)
    concept = models.ForeignKey(Concept, on_delete=models.CASCADE)

    def __str__(self):
        return self.concept.name + ' - Subconcept'

forms.py

class ConceptForm(forms.ModelForm):
    # Form for creating Concept objects
    class Meta:
        model = Concept
        fields = ['application', 'name', 'text', 'images', 'question', 'expected_completion_time', 'keywords', 'topic', 'course']


class SubconceptForm(forms.ModelForm):
    # Form for creating Subconcept objects which are linked by ManyToOne fields to Concept objects
    class Meta:
        model = Subconcepts
        fields = ['subconcept']  # Concept field excluded as will be set in view on form submission


class BaseSubconceptFormset(BaseFormSet):
    def clean(self):
        # Validate that all subconcepts are unique
        if any(self.errors):
            return
        subconcepts = []
        duplicates = False

        for form in self.forms:
            if form.cleaned_data:
                subconcept = form.cleaned_data('subconcept')

                if subconcept:
                    if subconcept in subconcepts:
                        duplicates = True
                    subconcepts.append(subconcept)

                if duplicates:
                    raise forms.ValidationError(
                        'Each key feature must be unique',
                        code='duplicate_subconcept'
                    )

views.py

def testformsets(request):

    # Forms for creating a concept with appropriate subconcepts
    SubconceptFormset = formset_factory(SubconceptForm, formset=BaseSubconceptFormset)

    if request.method == 'POST':
        concept_form = ConceptForm(request.POST)
        subconcept_formset = SubconceptFormset(request.POST)

        if concept_form.is_valid() and subconcept_formset.is_valid():
            concept = concept_form.save()

            new_subconcepts = []

            for subconcept_form in subconcept_formset:
                subconcept = subconcept_form.cleaned_data.get('subconcept')
                new_subconcepts.append(Subconcepts(subconcept=subconcept, concept=concept))

            try:
                with transaction.atomic():
                    # Add all new subconcepts at once
                    Subconcepts.objects.bulk_create(new_subconcepts)

                    # And notify our users that it worked
                    messages.success(request, 'You have added new material')

            except IntegrityError:  # If the transaction failed
                messages.error(request, 'There was an error saving your concept.')
                return redirect('pomodoro/index.html')

    else:
        concept_form = ConceptForm()
        subconcept_formset = SubconceptFormset()

    context = {
        'concept_form': concept_form,
        'subconcept_formset': subconcept_formset
    }
    return render(request, 'pomodoro/formset_test.html', context)

将日志记录语句添加到您的代码中。一个好的开始是记录每个决定的结果和每个重要函数调用的结果,如下所示:

def myView(request):

    import logging
    logging.basicConfig(filename='mylog.log', level=logging.DEBUG)

    if request.method == 'POST':
        logging.debug('request.method=POST')
        form = MyForm(request.POST)
        logging.debug('form=%s', form)

        if concept_form.is_valid():
            logging.debug('form is valid')
            myform = form.save()
            logging.debug('called form.save(), result=%s', myform)

        else:
            logging.debug('form is not valid')
    else:
        logging.debug('request.method is not POST')