Closed hugorodgerbrown closed 1 year ago
Closed as this is possible with a custom Flag model.
Adding this as an example, for future reference.
import datetime
from django.conf import settings
from django.db import models
from django.utils.timezone import now as tz_now
from waffle.models import AbstractUserFlag
class FeatureFlag(AbstractUserFlag):
"""
Drop-in replacement for Waffle's Flag model that supports custom
groups.
This is a subclass of Waffle's Flag model which adds the ability to
to target a "custom group" of users. This group is just a string,
which is then used in the `is_active_for_user` method override to
determine whether the flag should be active.
To add a new custom group add a const to the `CustomGroup` class,
and then add a matching model method with the same name as the
const. See the `anonymous_only` and `new_registrations` methods for
examples.
"""
class CustomGroup(models.TextChoices):
# when adding a new group, remember to add the appropriate
# method with the same name to the class.
ANONYMOUS_ONLY = "anonymous_only", "Anonymous users only"
NEW_REGISTRATIONS = "new_registrations", "Users registered in the last 30 days"
custom_group = models.CharField(
max_length=255,
blank=True,
null=True,
choices=CustomGroup.choices,
help_text="Custom group to enable this flag for",
)
class Meta:
verbose_name = "Feature Flag"
verbose_name_plural = "Feature Flags (ex. Waffle)"
def is_active_for_user(self, user):
if self.custom_group:
# will raise AttributeError if the custom group doesn't exist
return getattr(self, self.custom_group)(user)
# use the normal Waffle operation if no custom group is set.
return super().is_active_for_user(user)
# region: group methods
def anonymous_only(self, user: settings.AUTH_USER_MODEL) -> bool:
return user.is_anonymous
def new_registrations(self, user: settings.AUTH_USER_MODEL) -> bool:
return user.date_joined > tz_now() - datetime.timedelta(days=30)
# endregion: group methods
I will submit a PR for this, but thought I'd raise an issue first to explain my thinking.
We use waffle a lot, but there is a use case where it falls down (for us), and that is where we want to activate a flag based on a specific user attribute. An example might be "all users who have registered since XX", or "users who have performed this action".
I think this could be supported by having a list of functions set up that take a request and return a bool, that could be configured in settings and then attached to a flag. The
flag_is_active
functions would then use this to determine whether the outcome.These could then appear on the new flag page: