0

I'm relatively new to python/django and I'm not sure I'm doing this right

Suppose there are 2 different apps projects and items. The url I have in the items app is:

path('projects/<slug:project_slug>/items/', ItemListView.as_view())

And the cb-view:

class ItemListView(CanViewProjectMixin, ListView):
    model = Item

    def get(self, request, *args, **kwargs):
        self.project = Project.objects.get(slug=kwargs.get('project_slug'))
        return super(ItemListView, self).get(request, *args, **kwargs)

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super(ItemListView, self).get_context_data(**kwargs)
        context['project'] = self.project
        return context

This seems to work fine in the view, and it is passing the project object to the template via context

However, I'm not able to get self.project in the CanViewProjectMixin.dispatch() method.

Any help would be appreciated

Update

CanViewProjectMixin has a get_permission_object() method which retrieves the project object in the main project app views where project is retrieved via default get_object() or via self.project where the view is a child of project like in the example above.

def get_permission_object(self):
    if hasattr(self, 'project'):
        return self.project
    return (hasattr(self, 'get_object') and self.get_object() or
            getattr(self, 'object', None))

def dispatch(self, request, *args, **kwargs):
    self.object = self.get_permission_object()
    ...
    # do stuff with the object and return super()

On project views where project is retrieved via get_object() it works just fine, the problem is only on child views

4
  • get method runs after dispatch. If think you should attach self.project in dispatch if you need it there too. Commented Apr 3, 2019 at 13:50
  • Could you provide your class CanViewProjectMixin ? Commented Apr 3, 2019 at 13:50
  • Did u confirmed that get is called before dispatch? Normally dispatch is called before get, so self.project is not assigned yet in dispatch. Commented Apr 3, 2019 at 13:56
  • As the previous comments have noted, ItemListView defines self.project in the get method. That's too late if you want to use it in dispatch. You need to define self.project in dispatch (Django < 2.2) or setup as in my answer (Django >= 2.2). Commented Apr 3, 2019 at 15:22

1 Answer 1

1

The recently released Django 2.2 includes a new setup method which is called by the view before calling dispatch. This is the best place to initialize new view instance variables like self.project, without having to override dispatch.

class ItemListView(CanViewProjectMixin, ListView):
model = Item

def setup(self, request, *args, **kwargs):
    super().setup(request, *args, **kwargs)
    self.project = Project.objects.get(slug=kwargs.get('project_slug'))

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['project'] = self.project
    return context

As the docs point out, you must always call super() when you override setup.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.