修复 render() 在 Django 2.1 中得到了一个意外的关键字参数“renderer”

Jus*_*her 5 django django-forms django-views

我正在复活一些用于在 Django 1.9 中工作的旧代码。我正在尝试将此代码转换为 Django 2.1,但是作为我项目一部分的这个包存在一些兼容性问题。我正在寻找更正 render() 类型错误。

我已经像其他类似的帖子一样寻找可能已弃用的代码,但我找不到任何东西,例如小部件。我确实尝试在 forms.py 小部件中向主体添加渲染器,但这也不起作用。

视图.py

@login_required
def compose(request, recipient=None, form_class=ComposeForm,
        template_name='django_messages/compose.html', 
success_url=None, recipient_filter=None):
    """
    Displays and handles the ``form_class`` form to compose new 
messages.
    Required Arguments: None
    Optional Arguments:
    ``recipient``: username of a `django.contrib.auth` User, who should
                   receive the message, optionally multiple usernames
                   could be separated by a '+'
    ``form_class``: the form-class to use
    ``template_name``: the template to use
    ``success_url``: where to redirect after successfull submission
"""
if request.method == "POST":
    sender = request.user
    form = form_class(request.POST, recipient_filter=recipient_filter)
    if form.is_valid():
        form.save(sender=request.user)
        messages.info(request, _(u"Message successfully sent."))
        if success_url is None:
            success_url = reverse('messages_inbox')
        if 'next' in request.GET:
            success_url = request.GET['next']
        return HttpResponseRedirect(success_url)
else:
    form = form_class()
    if recipient is not None:
        recipients = [u for u in User.objects.filter(
            **{'%s__in' % get_username_field(): [r.strip() for r in recipient.split('+')]})]
        form.fields['recipient'].initial = recipients
return render(request, template_name, {
    'form': form,
})
Run Code Online (Sandbox Code Playgroud)

表单.py

class ComposeForm(forms.Form):
    """
    A simple default form for private messages.
    """
    recipient = CommaSeparatedUserField(label=_(u"Recipient"))
    subject = forms.CharField(label=_(u"Subject"), max_length=140)
    body = forms.CharField(label=_(u"Body"),
                           widget=forms.Textarea(attrs={'rows': '12', 'cols': '55'}))

    def __init__(self, *args, **kwargs):
        recipient_filter = kwargs.pop('recipient_filter', None)
        super(ComposeForm, self).__init__(*args, **kwargs)
        if recipient_filter is not None:
            self.fields['recipient']._recipient_filter = recipient_filter

    def save(self, sender, parent_msg=None):
        recipients = self.cleaned_data['recipient']
        subject = self.cleaned_data['subject']
        body = self.cleaned_data['body']
        message_list = []
        for r in recipients:
            msg = Message(
                sender=sender,
                recipient=r,
                subject=subject,
                body=body,
            )
            if parent_msg is not None:
                msg.parent_msg = parent_msg
                parent_msg.replied_at = timezone.now()
                parent_msg.save()
            msg.save()
            message_list.append(msg)
            if notification:
                if parent_msg is not None:
                    notification.send([sender], "messages_replied", {'message': msg, })
                    notification.send([r], "messages_reply_received", {'message': msg, })
                else:
                    notification.send([sender], "messages_sent", {'message': msg, })
                    notification.send([r], "messages_received", {'message': msg, })
        return message_list
Run Code Online (Sandbox Code Playgroud)

这是回溯:

  File "/Users/justinboucher/PycharmProjects/awaylm/django_messages/views.py", line 96, in compose
    'form': form,

  File "/anaconda3/envs/awaylm/lib/python3.6/site-packages/django/forms/boundfield.py", line 33, in __str__
    return self.as_widget()
  File "/anaconda3/envs/awaylm/lib/python3.6/site-packages/django/forms/boundfield.py", line 93, in as_widget
    renderer=self.form.renderer,
TypeError: render() got an unexpected keyword argument 'renderer'
[24/Jan/2019 03:57:26] "GET /messages/compose/ HTTP/1.1" 500 188278
Run Code Online (Sandbox Code Playgroud)

Bjo*_*orn 10

我遇到了同样的问题,结果证明它是我的依赖项之一。

首先,我向 Django 添加了一些调试信息,以便我可以查看导致问题的原因,因此我编辑了以下 Django 文件(在我的 virtualenv 中,以免破坏全局 Django 包中的任何内容):

vi 站点包/django/forms/boundfield.py

您的服务器日志回溯将为您识别特定文件。

我在第 50 行添加了“帮助”调用:

        if self.auto_id and 'id' not in widget.attrs:
            attrs.setdefault('id', self.html_initial_id if only_initial else self.auto_id)
        help(widget.render)
        return widget.render(
            name=self.html_initial_name if only_initial else self.html_name,
            value=self.value(),
            attrs=attrs,
            renderer=self.form.renderer,
        )
Run Code Online (Sandbox Code Playgroud)

然后我重新启动了我的 Django 服务器,以便它执行帮助功能,并且在服务器日志中我看到了以下内容:

Help on method render in module codemirror.widgets:

render(name, value, attrs=None) method of codemirror.widgets.CodeMirror instance
    Render the widget as an HTML string.
Run Code Online (Sandbox Code Playgroud)

这表明 Django 和 django-codemirror 之间存在兼容性问题,这是我用来在表单上呈现某些内容的依赖项。

我决定进一步修改 Django 文件,以允许没有渲染器参数的小部件。这不是一个理想的解决方案,但可以防止我不得不处理 django-codemirror 源文件。

        if self.auto_id and 'id' not in widget.attrs:
            attrs.setdefault('id', self.html_initial_id if only_initial else self.auto_id)
        # help(widget.render)
        try:
            return widget.render(
            name=self.html_initial_name if only_initial else self.html_name,
            value=self.value(),
            attrs=attrs,
            renderer=self.form.renderer,
        )
        except:
            return widget.render(
            name=self.html_initial_name if only_initial else self.html_name,
            value=self.value(),
            attrs=attrs
        )
Run Code Online (Sandbox Code Playgroud)

希望此过程有助于识别在您的环境中不兼容的特定对象。

编辑:此后我决定将 Django 改回默认代码,并在我的 django-codemirror 副本中进行了所需的更改。如果其他人想要修改 Django 以使用他们的其他依赖项,我将在上面留下我的答案。

还记录了以下问题:https : //github.com/onrik/django-codemirror/issues/3