14

I am learning Django and I am following a lynda.com course. In one of there courses "building an elearning site", the have the following code:

class CourseModuleUpdateView(TemplateResponseMixin, View):
    template_name = 'courses/manage/module/formset.html'
    course = None

    def get_formset(self, data=None):
        return ModuleFormSet(instance=self.course,
                             data=data)

    def dispatch(self, request, pk):
        self.course = get_object_or_404(Course, id=pk, owner=request.user)
        return super(CourseModuleUpdateView, self).dispatch(request, pk)

    def get(self, request, *args, **kwargs):
        formset = self.get_formset()
        return self.render_to_response({'course': self.course,
                                        'formset': formset})

    def post(self, request, *args, **kwargs):
        formset = self.get_formset(data=request.POST)
        if formset.is_valid():
            formset.save()
            return redirect('manage_course_list')
        return self.render_to_response({'course': self.course,
                                        'formset': formset})

But I am getting an error message from PyCharm (my IDE) on:

def dispatch(self, request, pk):

And the error is:

Signature of method 'CourseModuleUpdateView.dispatch()' does not match signature of base method in class 'View' less... (Ctrl+F1) 
This inspection detects inconsistencies in overriding method signatures.

Is there a way for me to troubleshoot the issue and see how to begin fixing the error? What is Pycharm even trying to tell me??

I am using python 3 and DJango 1.11

willer2k
  • 506
  • 1
  • 6
  • 17
  • About overriging the signature of a base method in general: https://stackoverflow.com/questions/6034662/python-method-overriding-does-signature-matter – Anton Tarasenko Dec 17 '18 at 18:53

2 Answers2

11

You're overriding a method dispatch of the parent class View whose signature is def dispatch(self, request, *args, **kwargs): which you can see from yours does not match.

Signature here means that the method arguments should match with parent class method you're overriding.

Sachin
  • 3,576
  • 1
  • 15
  • 24
  • 1
    So I just need to change: "def dispatch(self, request, pk):" to: "def dispatch(self, request, *args, **kwargs):" ? and if so, how do I pass the pk variable into the function now? – willer2k Aug 07 '17 at 21:17
  • I wouldn't suggest overriding `dispatch` to get an object from your model. You can get the object in either `get` or `post` methods you've defined. – Sachin Aug 08 '17 at 19:38
  • Even, if you are dead set on overriding it, you also need to override the method that calls `dispatch` and pass the `pk` attribute in the call and you can get the attribute in `args` or `kwargs`, according to how you have passed the argument. Eg - `dispatch(request, pk)` will build `args` as a tuple as `(pk, )` and `dispatch(request, pk=pk)` will build `kwargs` as a dict as `{ 'pk': pk }`. After that, you can pick the value from `args` or `kwargs`. – Sachin Aug 08 '17 at 19:41
  • yeah, I change my params of the methods and completely the same with the method of super class, and the warning disappear. – imissyou Apr 17 '20 at 08:17
8

Firstly you have to understand that this is a warning, not error.

Secondly: every argument (except of request) that is passed to view by Django is extracted from URL, as defined in urlpatterns. Django is using *args and **kwargs internally in class-based views so you can pass any argument without need for overwriting dispatch method.

And back to our warning: this warning is raised by many of static code analysis tools (including one built into PyCharm) to inform you that something here may be wrong, because original dispatch method has different signature. It doesn't mean that this is wrong and that's why there are always options to mute those warnings on selected code lines. You should of course look at every warning your editor raises, but that doesn't mean that every warning should be fixed.

You can fix it of course using:

    def dispatch(self, request, *args, **kwargs):
        id = args[0] # or id = kwargs['id'] if it is passed as keyword argument
        self.course = get_object_or_404(Course, id=pk, owner=request.user)
        return super(CourseModuleUpdateView, self).dispatch(request, pk)

but you can also ignore that and use as is. Your usage has some benefits, for example automatic validation on method invoke that all required arguments have been passed. Usage with default method signature (as above) has benefit in not raising that warning in your editor. It is up to you to decide which one is better.

GwynBleidD
  • 20,081
  • 5
  • 46
  • 77