【问题标题】:Django - How can I debug code which POST's when a bug seems to be in the view?Django - 当错误似乎在视图中时,如何调试 POST 的代码?
【发布时间】:2017-04-02 18:11:03
【问题描述】:

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

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

对于具体问题,我将把我的代码放在下面,以防这是一个简单的初学者错误,你们中的一个向导可以发现。为了我自己的目的,我尝试关注和调整this tutorial

模型.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)

【问题讨论】:

  • 在视图代码中添加日志语句。
  • concept = concept_form.save 你是说.save()(带括号)吗?否则你引用 save 方法,但你没有调用它。
  • @JohnGordon 感谢您发现这一点(errors_spotted_by_django_wizards += 1)。你是对的,我已经编辑过了。这似乎不是唯一的错误,因为在提交表单时仍然没有数据保存到数据库中。你能告诉我更多关于日志记录的信息吗?我不知道这个功能。也许您可以指导我参考一些文档?
  • 另见我的回答。

标签: python django forms django-forms formsets


【解决方案1】:

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

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')

【讨论】:

  • 谢谢,这正是我所需要的。它向我展示了我的错误所在,现在我需要弄清楚如何解决它。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-20
  • 1970-01-01
  • 1970-01-01
  • 2018-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多