修复render()在Django 2.1中获得了意外的关键字参数'renderer'

时间:2019-01-24 04:54:28

标签: django django-forms django-views

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

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

Views.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,
})

Forms.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

这是回溯:

  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

1 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,原来是我的依赖项之一。

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

vi site-packages / 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,
        )

然后,我重新启动了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.

这表明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
        )

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

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

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