1

The test_func doesn't appear to run at all. Right now I'm just checking if the user is staff, as an easy test. Here's the code:

class MyModelCreate(CreateView, UserPassesTestMixin):

    def test_func(self):
        print("checking if user passes test....")
        return self.request.user.is_staff

    model = MyModel
    ....

However, when I go to the create page for this model, anyone can edit it, and there is no output to the python console showing that the test_func runs.

The view is called:

urlpatterns = [
    ...
    url(r'^create/$', views.MyModelCreate.as_view(), name='my_model_create'),
]
43Tesseracts
  • 4,617
  • 8
  • 48
  • 94
  • 5
    You need to put the `CreateView` after the mixin. See [this answer](https://stackoverflow.com/a/38545128/1081569) and the [MRO (method resolution order) explanation](https://stackoverflow.com/questions/10018757/how-does-the-order-of-mixins-affect-the-derived-class) it points to. – Paulo Almeida Aug 26 '17 at 01:53
  • 1
    Thanks! That was it. Do you want to put this as an answer? This isn't mentioned in the docs at all. How would one know whether a mixin has to go first or not if it's not documented, without looking under the hood of the mixin? – 43Tesseracts Aug 26 '17 at 18:37
  • I'm glad you got it working. I won't put it as an answer because it's similar to that other question, and it's not my answer anyway. This is a general Python issue. There is [a warning about mixins](https://docs.djangoproject.com/en/1.11/topics/class-based-views/mixins/#using-django-s-class-based-view-mixins), but I suppose they felt it was outside the scope of Django's documentation to repeat the information in every mixin section, and I think it's reasonable. It is unfortunate when nothing breaks catastrophically and it just seems it doesn't work, because it makes is harder to debug. – Paulo Almeida Aug 27 '17 at 18:03

1 Answers1

3

In python the order of the classes matters because their methods override each other Your class based view should look like this:

class MyModelCreate(UserPassesTestMixin, CreateView):

def test_func(self):
    print("checking if user passes test....")
    return self.request.user.is_staff

model = MyModel
....