4.2 KiB
Survey Form AttributeError Fix
Problem
When accessing /surveys/send/, the application threw an AttributeError: 'User' object has no attribute 'get'.
Error Details
AttributeError at /surveys/send/
'User' object has no attribute 'get'
Request Method: GET
Request URL: http://localhost:8000/surveys/send/
Exception Location: /home/ismail/projects/HH/.venv/lib/python3.12/site-packages/django/utils/functional.py, line 253, in inner
Raised during: apps.surveys.ui_views.manual_survey_send
The error occurred during template rendering at line 93 of templates/surveys/manual_send.html.
Root Cause
The forms ManualSurveySendForm, ManualPhoneSurveySendForm, and BulkCSVSurveySendForm were being instantiated with a user parameter in the view:
form = ManualSurveySendForm(user) # In manual_survey_send view
form = ManualPhoneSurveySendForm(user) # In manual_survey_send_phone view
form = BulkCSVSurveySendForm(user) # In manual_survey_send_csv view
However, these forms did not have custom __init__ methods to accept the user parameter. When Django tried to pass the user object as the first positional argument, the form's default __init__ method expected a dictionary-like object (data) but received a User object instead.
Solution
Added custom __init__ methods to all three forms that:
- Accept a
userparameter as the first argument - Call the parent class's
__init__method correctly - Store the user object for potential later use
- Filter the
survey_templatequeryset to show only templates from the user's hospital
Changes Made to apps/surveys/forms.py
1. ManualSurveySendForm
class ManualSurveySendForm(forms.Form):
"""Form for manually sending surveys to patients or staff"""
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = user
# Filter survey templates by user's hospital
if user.hospital:
self.fields['survey_template'].queryset = SurveyTemplate.objects.filter(
hospital=user.hospital,
is_active=True
)
# ... rest of the form fields
2. ManualPhoneSurveySendForm
class ManualPhoneSurveySendForm(forms.Form):
"""Form for sending surveys to a manually entered phone number"""
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = user
# Filter survey templates by user's hospital
if user.hospital:
self.fields['survey_template'].queryset = SurveyTemplate.objects.filter(
hospital=user.hospital,
is_active=True
)
# ... rest of the form fields
3. BulkCSVSurveySendForm
class BulkCSVSurveySendForm(forms.Form):
"""Form for bulk sending surveys via CSV upload"""
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = user
# Filter survey templates by user's hospital
if user.hospital:
self.fields['survey_template'].queryset = SurveyTemplate.objects.filter(
hospital=user.hospital,
is_active=True
)
# ... rest of the form fields
Note: BulkCSVSurveySendForm already had an __init__ method but it was defined after the field definition, which could cause issues. It's been moved before the field definitions for consistency.
Benefits
- Fixes the AttributeError: Forms can now be instantiated with a user parameter
- Improved Security: Survey templates are filtered by the user's hospital, preventing users from seeing templates they shouldn't have access to
- Better User Experience: Users only see relevant survey templates in the dropdown
- Consistency: All three manual survey send forms now have the same initialization pattern
Testing
To verify the fix:
- Navigate to
/surveys/send/ - The page should load without errors
- The survey template dropdown should only show templates from the user's hospital
- Test the phone-based survey send at
/surveys/send/phone/ - Test the CSV-based bulk send at
/surveys/send/csv/
All three views should now work correctly.