Incidentally, our new portal is built on Django 1.5, and one of its new features is the ability to have fully customizable user models in django.contrib.auth. Sweet! This is great for us, as we are now able to move away from the static user model that existed within Django previously; however, despite Waffle’s best efforts to stay compatible, defining custom users can break Waffle. Boo.
Read about the issue on Github here.
Until a fix is implemented, here is a breakdown of the workaround that we used to keep us moving forward.
The Heart of The Issue
- user.is_authenticated() method exists
- user.is_staff property exists
- user.is_superuser property exists
- user.groups.all() returns all Group objects attached to the user - making the assumption that you are using django.contrib.auth.group and linking it to the user model as a foreign key field
This clashes with Django 1.5’s minimum requirements for a custom user model (found here):
- have an integer primary key
- have a unique field for identification purposes (a “username”)
- provide a way to address the user in ‘short’ and ‘long’ forms
Some of Waffle’s requirements are satisfied if you go through the effort of making the user model compatible with django.contrib.admin, or by having the model inherit AbstractBaseUser. However, unless your model satisfies all four of Waffle’s assumptions, it will break the code. Luckily, there are easy ways to satisfy all requirements without having to run to your database to alter tables.
Faking is_staff and is_superuser Model Fields
Faking the Groups Many-to-Many Field
We start by defining a fake property the same way we did above for is_superuser and is_staff. However, this time we make it return a dummy object with an all() method under it: