get_form 将 Django 升级到 1.10 后抛出 TypeError

get_form throws TypeError after upgrading Django to 1.10

我最近从 1.4 升级到 1.11(增量),从 1.9 升级到 1.10 后,我遇到了 get_form() 的问题。似乎我的上下文不包含 "form" 并且当调用超级 get_context_data 时,它会尝试传递一个空的 get_form() 调用来填写表单。知道为什么现在会出错吗?

Internal Server Error: /messages/threads/6/
Traceback (most recent call last):
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\core\handlers\exception.py", line 41, in inner
    response = get_response(request)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\core\handlers\base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\contrib\auth\decorators.py", line 23, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\views\generic\base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\LT1\project\messages\views.py", line 93, in dispatch
    return super(MemoCreateView, self).dispatch(request, *args, **kwargs)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\views\generic\base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\views\generic\edit.py", line 213, in get
    return super(BaseCreateView, self).get(request, *args, **kwargs)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\views\generic\edit.py", line 174, in get
    return self.render_to_response(self.get_context_data())
  File "C:\Users\LT1\project\messages\views.py", line 96, in get_context_data
    context = super(MemoCreateView, self).get_context_data(**kwargs)
  File "C:\Users\LT\Envs\django111\lib\site-packages\django\views\generic\edit.py", line 93, in get_context_data
    kwargs['form'] = self.get_form()
TypeError: get_form() takes exactly 2 arguments (1 given)
"GET /messages/threads/6/ HTTP/1.1" 500 113089

urls.py

from django.conf.urls import url, include
from django.contrib.auth.decorators import login_required
from django.views.generic import ListView
from django.views.generic.base import RedirectView
from .models import *
from .views import *

urlpatterns = [
    url(r'^$', login_required(RedirectView.as_view(url='/messages/threads/')), name='messages_index'),
    url(r'^threads/$', login_required(ThreadListView.as_view()), name='messages_thread_index'),
    url(r'^threads/create/$', login_required(ThreadCreateView.as_view()), name='messages_thread_create'),
    url(r'^threads/to-user/(?P<user_id>[0-9]+)/create/$', login_required(PrepopulatedUserThreadCreateView.as_view()), name='messages_prepopulated_user_thread_create'),
    url(r'^threads/to-group/(?P<group_id>[0-9]+)/create/$', login_required(PrepopulatedGroupThreadCreateView.as_view()), name='messages_prepopulated_group_thread_create'),
    url(r'^threads/(?P<thread_id>[0-9]+)/$', login_required(MemoCreateView.as_view()), name='messages_memo_index'),
    url(r'^ajax/search/$', login_required(SearchView.as_view()), name='messages_ajax_search'),
    url(r'^ajax/queue/$', login_required(QueueView.as_view()), name='messages_ajax_queue'),
]

views.py

class MemoCreateView(CreateView):
    model = Memo
    form_class = MemoForm

    def dispatch(self, request, *args, **kwargs):
        self.thread = Thread.objects.get(id=kwargs['thread_id'])
        if not user_has_permission(request.user, self.thread, 'can_message'):
            raise PermissionDenied('You do not have permission to view this thread.')
        self.thread.read_by_role.users.add(request.user)
        return super(MemoCreateView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(MemoCreateView, self).get_context_data(**kwargs)
        context['thread'] = self.thread
        context['participants_form'] = ThreadForm
        return context

    def get_form(self, form_class):
        if self.thread:
            if self.request.method == 'GET':
                participants = self.thread.participant_role.users.all()
                users_csv = ','.join([str(user.id) for user in self.thread.participant_role.users.all()])
                return form_class({'participants': users_csv,})

        '''
            elif self.request.method == 'POST':
                return form_class(self.request.POST, instance=self.shared_object)
        else:
            if self.request.method == 'POST':
                return form_class(self.request.POST)
        '''
        return super(MemoCreateView, self).get_form(form_class)

    def form_valid(self, form):
        '''
        self.object = form.save(commit=False)
        self.object.author = self.request.user
        self.object.thread = self.thread
        self.object.save()
        '''

        memo = form.save(commit=False)
        memo.author = self.request.user
        memo.thread = self.thread
        memo.save()

        participants = []
        participant_ids = form.cleaned_data['participants'].replace(' ', '').split(',')
        for participant_id in participant_ids:
            if participant_id:
                participants.append(User.objects.get(id=participant_id))

        groups = []
        group_ids = form.cleaned_data['groups'].replace(' ', '').split(',')
        for group_id in group_ids:
            if group_id:
                groups.append(Group.objects.get(id=group_id))

        for group in groups:
            if not user_has_permission(self.request.user, group, 'can_message'):
                raise PermissionDenied('You do not have permission to message to the group "' + group.name + '"')

        thread = memo.thread
        #thread.subject = form.cleaned_data['subject']
        thread.creator = self.request.user
        thread.save()

        thread.participant_role.users.add(*participants)

        for group in groups:
            thread.participant_role.users.add(*list(group.owner_role.users.all()))
            thread.participant_role.users.add(*list(group.moderator_role.users.all()))
            thread.participant_role.users.add(*list(group.member_role.users.all()))
        self.success_url = thread.get_absolute_url()

        return super(MemoCreateView, self).form_valid(form)

问题库行:

C:\Users\LT\Envs\django111\lib\site-packages\django\views\generic\edit.py in get_context_data
        return self.render_to_response(self.get_context_data(form=form))
    def get_context_data(self, **kwargs):
        """
        Insert the form into the context dict.
        """
        if 'form' not in kwargs:
            kwargs['form'] = self.get_form() ...
        return super(FormMixin, self).get_context_data(**kwargs)
class ModelFormMixin(FormMixin, SingleObjectMixin):
    """
    A mixin that provides a way to show and handle a modelform in a request.

我试过将视图更改为

 def get_form(self,  form_class=None):
        if form_class is None:
            form_class = self.form_class
        if self.thread:
            if self.request.method == 'GET':
                participants = self.thread.participant_role.users.all()
                users_csv = ','.join([str(user.id) for user in self.thread.participant_role.users.all()])
                return form_class({'participants': users_csv,})

        '''
            elif self.request.method == 'POST':
                return form_class(self.request.POST, instance=self.shared_object)
        else:
            if self.request.method == 'POST':
                return form_class(self.request.POST)
        '''
        return super(MemoCreateView, self).get_form(form_class)

如评论中所建议的那样,但它并没有改变任何东西。似乎 django 视图库本身正在调用一个没有参数的 get_form - 我怎样才能防止这种情况发生?

As of Django 1.8, the get_form() method doesn’t require a form_class to be provided anymore. As of Django 1.10,您必须在自定义 get_form 方法中为 form_class 定义默认值。

您可以按如下方式更改。

def get_form(self, form_class=None):
    if form_class is None:
        form_class = self.form_class
    ...