Group-Based Features
Group-based feature toggles allow developers to show or hide features based on a user's membership in Django groups. This system is used for alpha/beta testing, gradual rollouts, and access control.
Implementation
The feature toggle system uses a custom Django template filter that checks group membership.
Template Tag
The in_group
filter is defined in core/templatetags/group_tags.py
:
@register.filter
def in_group(user, group_name):
"""Check if a user is in a specific group by name."""
if not user or not user.is_authenticated:
return False
try:
group = Group.objects.get(name=group_name)
return user.groups.filter(pk=group.pk).exists()
except Group.DoesNotExist:
return False
Usage in Templates
Load the template tag library:
<div data-gb-custom-block data-tag="load"></div>
Check group membership:
<div data-gb-custom-block data-tag="if" data-0='Campaigns Alpha'>
<!-- Content only visible to group members -->
</div>
Examples
Navigation Items
<div data-gb-custom-block data-tag="if" data-0='Campaigns Alpha'>
<li class="nav-item">
<a class="nav-link
<div data-gb-custom-block data-tag="active_view" data-0='core:campaigns'></div>"
href="<div data-gb-custom-block data-tag="url" data-0='core:campaigns'></div>
">Campaigns</a>
</li>
</div>
Feature Sections
<div data-gb-custom-block data-tag="if" data-0='Beta Features'>
<div class="card">
<h2>Beta Features</h2>
<!-- Beta content -->
</div>
</div>
Conditional Elements
<div data-gb-custom-block data-tag="if" data-0='Premium Users'>
<button class="btn btn-primary">Advanced Export</button>
<div data-gb-custom-block data-tag="else"></div>
<button class="btn btn-secondary" disabled>
Advanced Export (Premium Only)
</button>
</div>
Managing Groups
Creating Groups
Via Django Admin:
Navigate to
/admin/auth/group/
Click "Add Group"
Enter group name
Save
Via Django Shell:
from django.contrib.auth.models import Group
Group.objects.create(name="Feature Group Name")
Via Data Migration:
def create_groups(apps, schema_editor):
Group = apps.get_model('auth', 'Group')
Group.objects.create(name="Campaigns Alpha")
Adding Users to Groups
Via Django Admin:
Navigate to user's detail page
Select groups in "Groups" field
Save
Via Django Shell:
from django.contrib.auth.models import User, Group
user = User.objects.get(username="username")
group = Group.objects.get(name="Campaigns Alpha")
user.groups.add(group)
Testing
Test group membership in unit tests:
def test_feature_visible_to_group_members(self):
user = User.objects.create_user(username="test")
group = Group.objects.create(name="Test Feature")
user.groups.add(group)
response = self.client.get('/feature-url/')
self.assertContains(response, "Feature Content")
Current Feature Groups
Campaigns Alpha
Early access to campaign features
Campaign navigation link, campaign creation
Best Practices
Descriptive Names: Use clear group names like "Campaigns Alpha", "Beta Testers"
Document Groups: Maintain a list of active groups and their purposes
Fail Safe: The filter returns
False
for non-existent groupsClean Up: Remove groups after features are fully released
Test Coverage: Include tests for both group members and non-members
Security Considerations
Group membership is checked server-side
Template filter prevents rendering, not just hiding with CSS
Groups should not be used for critical security permissions
Use Django's permission system for access control
Performance
The in_group
filter:
Makes one database query per check
Results are not cached by default
Consider using
select_related('groups')
for user queries if checking many groups
Last updated