-
-
Notifications
You must be signed in to change notification settings - Fork 291
feat: Modularize Sizzle as pluggable Django app (#4712) #4782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Modularize Sizzle as pluggable Django app (#4712) #4782
Conversation
…r avoiding any breaking changes)
Co-authored-by: DonnieBLT <[email protected]>
Co-authored-by: DonnieBLT <[email protected]>
Co-authored-by: DonnieBLT <[email protected]>
Co-authored-by: DonnieBLT <[email protected]>
Replace custom OAuth callback implementations with allauth's built-in provider callback views. This ensures proper OAuth2 flow handling and follows django-allauth best practices. - Use github_views.oauth2_callback, google_views.oauth2_callback, facebook_views.oauth2_callback directly in URL patterns - Remove unused custom callback view classes - Remove unused OAuth2CallbackView import - Remove unused safe_redirect_allowed and urllib imports - Format imports according to isort and Ruff requirements fixes: OWASP-BLT#4753
Co-authored-by: DonnieBLT <[email protected]>
Co-authored-by: DonnieBLT <[email protected]>
Co-authored-by: DonnieBLT <[email protected]>
…cessor for sidenav availability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (3)
sizzle/management/commands/cron_send_reminders.py (2)
176-191: Guard domain lookup for reminder links.Direct access to
settings.PRODUCTION_DOMAINwill raiseAttributeErrorin projects that don't define this BLT-specific setting, breaking the pluggable app promise.
201-229: Domain references in HTML template need configuration.The HTML email template also hardcodes
settings.PRODUCTION_DOMAIN, which is part of the same pluggability issue.sizzle/views.py (1)
296-296: Remove debug print statement.A
print()statement remains in production code and should be replaced with proper logging.
🧹 Nitpick comments (3)
sizzle/management/commands/slack_daily_timelogs.py (1)
103-108: Consider reusing the utility function.A similar
format_timedeltafunction exists insizzle/utils/__init__.py(lines 20-27). While the output formats differ slightly ("Xh Ym Zs" vs "X hours, Y minutes, Z seconds"), you could standardize on one format and eliminate this duplication.sizzle/utils/model_loader.py (2)
101-139: Consider exception chaining for clearer tracebacks.The core model loaders raise
ImproperlyConfiguredwhen models aren't found, but don't chain the originalLookupError. Addingraise ... from ewould preserve the full exception context for debugging.Example for one function:
except LookupError as e: - raise ImproperlyConfigured( + raise ImproperlyConfigured( f"Could not load ReminderSettings model from sizzle app. " f"Make sure sizzle migrations have been run. Error: {e}" - ) + ) from e
142-153: Remove unnecessary noqa directives.The
# noqacomments on lines 148-149 are unnecessary since the imports are actually used (they verify the modules can be imported).Apply this diff:
try: - from slack_bolt import App # noqa - from slack_sdk.web import WebClient # noqa + from slack_bolt import App + from slack_sdk.web import WebClient
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (9)
sizzle/admin.py(1 hunks)sizzle/context_processors.py(1 hunks)sizzle/management/commands/cron_send_reminders.py(1 hunks)sizzle/management/commands/slack_daily_timelogs.py(1 hunks)sizzle/migrations/0001_initial.py(1 hunks)sizzle/models.py(1 hunks)sizzle/utils/__init__.py(1 hunks)sizzle/utils/model_loader.py(1 hunks)sizzle/views.py(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- sizzle/admin.py
🧰 Additional context used
🪛 Ruff (0.14.4)
sizzle/context_processors.py
7-7: Unused function argument: request
(ARG001)
sizzle/utils/__init__.py
11-11: Probable use of requests call without timeout
(S113)
15-15: Consider moving this statement to an else block
(TRY300)
16-16: Do not catch blind exception: Exception
(BLE001)
sizzle/utils/model_loader.py
109-112: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
109-112: Avoid specifying long messages outside the exception class
(TRY003)
123-125: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
123-125: Avoid specifying long messages outside the exception class
(TRY003)
136-139: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
136-139: Avoid specifying long messages outside the exception class
(TRY003)
148-148: Unused blanket noqa directive
Remove unused noqa directive
(RUF100)
149-149: Unused blanket noqa directive
Remove unused noqa directive
(RUF100)
151-151: Consider moving this statement to an else block
(TRY300)
sizzle/management/commands/cron_send_reminders.py
32-32: Unused method argument: args
(ARG002)
32-32: Unused method argument: options
(ARG002)
107-107: Do not catch blind exception: Exception
(BLE001)
132-132: Do not catch blind exception: Exception
(BLE001)
133-133: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
133-133: Use explicit conversion flag
Replace with conversion flag
(RUF010)
150-150: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
154-154: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
242-242: Do not catch blind exception: Exception
(BLE001)
244-244: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
244-244: Use explicit conversion flag
Replace with conversion flag
(RUF010)
256-256: Consider moving this statement to an else block
(TRY300)
258-258: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
258-258: Use explicit conversion flag
Replace with conversion flag
(RUF010)
sizzle/views.py
224-224: Loop control variable date not used within loop body
Rename unused date to _date
(B007)
259-259: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
316-316: Local variable e is assigned to but never used
Remove assignment to unused variable e
(F841)
338-338: Loop control variable date not used within loop body
Rename unused date to _date
(B007)
sizzle/migrations/0001_initial.py
12-14: Avoid specifying long messages outside the exception class
(TRY003)
28-116: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
sizzle/models.py
52-52: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
53-55: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
76-79: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
sizzle/management/commands/slack_daily_timelogs.py
12-12: Unused method argument: args
(ARG002)
12-12: Unused method argument: kwargs
(ARG002)
46-46: Do not catch blind exception: Exception
(BLE001)
97-97: Do not catch blind exception: Exception
(BLE001)
120-120: Do not catch blind exception: Exception
(BLE001)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (14)
sizzle/context_processors.py (1)
7-29: LGTM! Context processor correctly implements feature toggle.The implementation now properly honors the
SIZZLE_SHOW_SIDENAVsetting before checking template existence, addressing the previous review feedback. The unusedrequestparameter is required by Django's context processor signature.sizzle/utils/__init__.py (1)
20-27: LGTM! Duration formatting is correct.The implementation correctly converts timedelta to a human-readable format using appropriate time division.
sizzle/management/commands/cron_send_reminders.py (1)
56-81: LGTM! Midnight window wrap-around correctly implemented.The time window filtering now properly handles cases where the reminder window crosses midnight using Django Q objects, addressing the previous review feedback.
sizzle/management/commands/slack_daily_timelogs.py (1)
40-41: LGTM! Timezone-aware timestamp correctly implemented.The command now uses
timezone.now()instead of naivedatetime.utcnow(), fixing the previous timezone comparison issue.sizzle/utils/model_loader.py (1)
156-195: LGTM! Validation logic correctly checks model availability.The validation function properly checks core and optional models based on feature flags, providing useful diagnostic information.
sizzle/models.py (3)
12-36: LGTM! TimeLog model correctly uses swappable references.The model now properly uses
settings.AUTH_USER_MODELand configurableSIZZLE_ORGANIZATION_MODEL, addressing previous review feedback.
38-59: LGTM! DailyStatusReport model uses correct user reference.The model now consistently uses
settings.AUTH_USER_MODELinstead of a direct User import, fixing the previous inconsistency.
61-100: LGTM! ReminderSettings model uses correct user reference.The OneToOneField now properly references
settings.AUTH_USER_MODEL, and the timezone conversion logic in thesavemethod is correctly implemented.sizzle/views.py (4)
17-18: LGTM! Imports now use dynamic model loading.The file correctly imports from
sizzle.utilsandsizzle.utils.model_loader, addressing the previous hardcoded dependency onwebsite.models.
175-191: LGTM! Authentication and authorization properly implemented.The view now has the
@login_requireddecorator and includes authorization logic to restrict access to report owners and staff, addressing previous review feedback.
316-319: LGTM! Exception handling properly narrowed.The exception handling now catches specific Django exceptions rather than bare
Exception, and useslogger.exceptionfor proper traceback logging, addressing previous review feedback.
347-349: LGTM! Null check for end_time properly implemented.The code now checks if
end_timeisNonebefore callingstrftime(), preventing theAttributeErrorthat was flagged in the previous review.sizzle/migrations/0001_initial.py (2)
9-20: LGTM! Migration now uses swappable organization model.The migration correctly uses
SIZZLE_ORGANIZATION_MODELwith swappable dependencies and fails fast with a clear error message if not configured, addressing the previous review feedback about hardcoded dependencies.
28-116: LGTM! Migration operations correctly reference swappable models.All model operations properly use
settings.AUTH_USER_MODELandSIZZLE_ORGANIZATION_MODEL, ensuring the migration is compatible with different project configurations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
sizzle/views.py (1)
297-297: Replace debug print with structured loggingThat bare
print(...)(previously flagged) still writes to stdout in production. Please switch to the module logger so the message respects configured handlers.- print(previous_work, next_plan, blockers, goal_accomplished, current_mood) + logger.debug( + "Creating daily status report: previous_work=%s, next_plan=%s, blockers=%s, goal_accomplished=%s, current_mood=%s", + previous_work, + next_plan, + blockers, + goal_accomplished, + current_mood, + )
🧹 Nitpick comments (1)
sizzle/context_processors.py (1)
7-29: Consider enhancing documentation for integrators.The context processor logic is sound, but the docstring could be more helpful. Consider documenting:
- The returned context keys (
sizzle_has_sidenav,parent_base) and their purposes- That
includes/sidenav.html(line 16) is expected to be provided by the integrating project, not by the Sizzle app itself- Configuration settings referenced (
SIZZLE_SHOW_SIDENAV,SIZZLE_PARENT_BASE)Example enhancement:
def sizzle_context(request): - """Provide sizzle-specific template context for seamless integration""" + """ + Provide sizzle-specific template context for seamless integration. + + Returns: + dict: Context with: + - sizzle_has_sidenav (bool): Whether sidenav template is available. + Controlled by SIZZLE_SHOW_SIDENAV setting and presence of + includes/sidenav.html template (provided by integrating project). + - parent_base (str|None): Base template path from SIZZLE_PARENT_BASE + setting, allowing Sizzle templates to extend project's base layout. + """
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (7)
sizzle/context_processors.py(1 hunks)sizzle/management/commands/cron_send_reminders.py(1 hunks)sizzle/management/commands/slack_daily_timelogs.py(1 hunks)sizzle/migrations/0001_initial.py(1 hunks)sizzle/models.py(1 hunks)sizzle/utils/__init__.py(1 hunks)sizzle/views.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
sizzle/management/commands/cron_send_reminders.py
32-32: Unused method argument: args
(ARG002)
32-32: Unused method argument: options
(ARG002)
106-106: Do not catch blind exception: Exception
(BLE001)
131-131: Do not catch blind exception: Exception
(BLE001)
132-132: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
132-132: Use explicit conversion flag
Replace with conversion flag
(RUF010)
149-149: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
153-153: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
255-255: Do not catch blind exception: Exception
(BLE001)
257-257: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
257-257: Use explicit conversion flag
Replace with conversion flag
(RUF010)
269-269: Consider moving this statement to an else block
(TRY300)
271-271: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
271-271: Use explicit conversion flag
Replace with conversion flag
(RUF010)
sizzle/context_processors.py
7-7: Unused function argument: request
(ARG001)
sizzle/migrations/0001_initial.py
12-12: Avoid specifying long messages outside the exception class
(TRY003)
26-114: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
sizzle/views.py
225-225: Loop control variable date not used within loop body
Rename unused date to _date
(B007)
260-260: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
317-317: Local variable e is assigned to but never used
Remove assignment to unused variable e
(F841)
339-339: Loop control variable date not used within loop body
Rename unused date to _date
(B007)
sizzle/management/commands/slack_daily_timelogs.py
13-13: Unused method argument: args
(ARG002)
13-13: Unused method argument: kwargs
(ARG002)
47-47: Do not catch blind exception: Exception
(BLE001)
98-98: Do not catch blind exception: Exception
(BLE001)
121-121: Do not catch blind exception: Exception
(BLE001)
sizzle/models.py
54-54: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
55-57: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
80-83: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
sizzle/utils/__init__.py
15-15: Consider moving this statement to an else block
(TRY300)
16-16: Do not catch blind exception: Exception
(BLE001)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
🔇 Additional comments (3)
sizzle/context_processors.py (1)
7-7: Unusedrequestparameter is required by Django.The Ruff warning about the unused
requestparameter is a false positive. Django context processors must be callables that accept a single argument — the current HttpRequest, making the parameter mandatory by framework design. Optionally, you could prefix it with an underscore (_request) to signal intentional non-use, though leaving it asrequestis standard Django practice.sizzle/migrations/0001_initial.py (2)
15-18: LGTM once the configuration check is moved here.The dynamic dependency generation is implemented correctly and supports swappable models as intended.
26-114: Safely ignore the RUF012 static analysis warning.The Ruff warning about
operationsneedingClassVarannotation is a false positive—Django migrations use these as ordinary class attributes by design.The model definitions are correct:
- Proper swappable model references
- Appropriate field types, constraints, and indexes
- Good related_name choices to avoid conflicts
|
I was getting this ci/cd error, as it was good prior to this, can you help with it. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 1500 🏁 Script executed: Length of output: 1580 🏁 Script executed: Length of output: 3764 @mdkaifansari04 I found the issue! The problem is in your migration file Root CauseThe migration is using a bare variable Current (incorrect): from sizzle.conf import SIZZLE_ORGANIZATION_MODEL
# ...
to=SIZZLE_ORGANIZATION_MODEL, # ❌ WrongShould be: to=settings.SIZZLE_ORGANIZATION_MODEL, # ✅ CorrectThe FixUpdate 1. Remove the import from sizzle.conf: # Remove this line:
from sizzle.conf import SIZZLE_ORGANIZATION_MODEL2. Update the _dependencies function: def _dependencies():
from django.conf import settings
deps = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]
# Check if SIZZLE_ORGANIZATION_MODEL is configured
org_model = getattr(settings, 'SIZZLE_ORGANIZATION_MODEL', None)
if not org_model:
raise ImproperlyConfigured(
"SIZZLE_ORGANIZATION_MODEL must be configured before running sizzle migrations."
)
deps.append(migrations.swappable_dependency(org_model))
return deps3. Update the TimeLog CreateModel operation: migrations.CreateModel(
name="TimeLog",
fields=[
# ... other fields ...
(
"organization",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="sizzle_time_logs",
to=settings.SIZZLE_ORGANIZATION_MODEL, # ✅ Changed from SIZZLE_ORGANIZATION_MODEL
),
),
# ... rest of fields ...
],
)Why This Fixes ItDjango's migration framework needs swappable model references to be accessed through After making these changes, the migration should work correctly in your CI/CD environment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (3)
sizzle/migrations/0001_initial.py (2)
11-12: Critical: Remove the duplicate module-level configuration check.The module-level
raiseon lines 11-12 will crash when Django imports this file to discover migrations (e.g.,showmigrations,migrate --list), even though_dependencies()already performs the same check at runtime. This was flagged in a previous review but the module-level check was not removed.Apply this diff to remove the duplicate check:
from sizzle.conf import SIZZLE_ORGANIZATION_MODEL -if not SIZZLE_ORGANIZATION_MODEL: - raise ImproperlyConfigured("SIZZLE_ORGANIZATION_MODEL must be configured before running sizzle migrations.") - def _dependencies(): from django.conf import settingsThe check inside
_dependencies()(lines 21-26) will still enforce the requirement when the migration actually runs.
15-27: Add the missing return statement in_dependencies()function.The function builds a dependencies list but lacks an explicit return statement. Since the function is called on line 33 and assigned to the Migration class's
dependenciesattribute, it will currently returnNoneinstead of the list, causing Django migration processing to fail.deps.append(migrations.swappable_dependency(org_model)) + return depssizzle/views.py (1)
297-297: Remove the debug print statement.A
print()statement remains in production code on line 297. This was previously flagged for replacement with proper logging but appears to still be present.Apply this diff to replace it with structured logging:
- print(previous_work, next_plan, blockers, goal_accomplished, current_mood) + logger.debug( + "Creating daily status report: previous_work=%s, next_plan=%s, blockers=%s, " + "goal_accomplished=%s, current_mood=%s", + previous_work, next_plan, blockers, goal_accomplished, current_mood + )
🧹 Nitpick comments (5)
sizzle/views.py (5)
225-225: Unused loop variabledate.The loop variable
dateis not used in the loop body; rename it to_dateto indicate it's intentionally unused.- for date, logs in grouped_logs.items(): + for _date, logs in grouped_logs.items():
260-260: Unused variablecreated.The
createdvariable fromToken.objects.get_or_create()is never used; prefix it with an underscore.- token, created = Token.objects.get_or_create(user=request.user) + token, _created = Token.objects.get_or_create(user=request.user)
262-264: Clarify Organization model availability check.The check
if Organization:on line 262 verifies the model class exists (in caseget_organization_model()returnsNonewhen SIZZLE_ORGANIZATION_MODEL is not configured). While this handles optional organization support correctly, consider adding a brief inline comment to clarify the intent for maintainability.organizations_list = [] - if Organization: + if Organization: # Organization model is optional; may be None if not configured organizations_list_queryset = Organization.objects.all().values("url", "name") organizations_list = list(organizations_list_queryset)
317-320: Unused exception variablee.The exception variable
eis captured but never used in the handler; remove it or use it in logging.- except (ValidationError, IntegrityError) as e: + except (ValidationError, IntegrityError): logger.exception("Error creating daily status report") messages.error(request, "An error occurred while submitting your report. Please try again.") return redirect("sizzle")
340-340: Unused loop variabledate.The loop variable
dateis not used in the loop body; rename it to_dateto indicate it's intentionally unused.- for date, logs in grouped_logs.items(): + for _date, logs in grouped_logs.items():
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting
📒 Files selected for processing (2)
sizzle/migrations/0001_initial.py(1 hunks)sizzle/views.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.4)
sizzle/migrations/0001_initial.py
12-12: Avoid specifying long messages outside the exception class
(TRY003)
23-25: Avoid specifying long messages outside the exception class
(TRY003)
35-123: Mutable class attributes should be annotated with typing.ClassVar
(RUF012)
sizzle/views.py
225-225: Loop control variable date not used within loop body
Rename unused date to _date
(B007)
260-260: Unpacked variable created is never used
Prefix it with an underscore or any other dummy variable pattern
(RUF059)
317-317: Local variable e is assigned to but never used
Remove assignment to unused variable e
(F841)
340-340: Loop control variable date not used within loop body
Rename unused date to _date
(B007)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Tests
- GitHub Check: docker-test
DonnieBLT
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please apply this to the new sizzle repo and for the blt repo the change will be adding the sizzle to requirements and deleting the code so it migrates seamlessly
|
Sure @DonnieBLT, I'll make the updates for BLT as well as for sizzle. Thanks for the feedback. |
|
follow up on the Sizzle repo |
|
Follwing up with other pr in sizzle repo. |
Summary
FIxes: OWASP-BLT/Sizzle#1
This PR implements Issue OWASP-BLT/Sizzle#1 - converting the Sizzle daily check-in and time tracking feature into a standalone, pluggable Django app. This is part of the larger initiative (#4709) to modularize OWASP BLT into reusable components.[1][2]
Demo Video
Uploading 2025-11-12 18-13-12.mov…
What Changed
Core Separation
sizzle/Django app with complete isolationDailyStatusReport,TimeLog,ReminderSettingswebsite/views/organization.pytosizzle/views.pysizzle/templates/sizzle/sizzle/static/sizzle/Pluggability Features
AUTH_USER_MODELpattern[2][1]apps.get_model()for external dependencies[1]File Structure
Technical Implementation
1. Settings-Based Configuration (
sizzle/conf.py)Following Django best practices, external dependencies are configurable via settings:[1][2]
Why this approach?
AUTH_USER_MODEL[1]2. Dynamic Model Loading (
sizzle/utils/model_loader.py)External models are loaded dynamically to avoid hardcoded imports:[1]
Benefits:
from website.models import SlackIntegration3. Template Independence
Created
sizzle/templates/sizzle/base.htmlas a minimal standalone base:[2]All Sizzle templates now extend
sizzle/base.htmlinstead ofbase.html.[2]Users can override by creating
their_project/templates/sizzle/base.htmlto match their site design.[2]4. Optional Slack Integration
Management commands check for Slack availability gracefully:
🗄️ Database Migration Strategy
Phase 1: Create New Tables
Creates:
sizzle_dailystatusreportsizzle_timelogsizzle_remindersettingsPhase 2: Data Migration
Created
sizzle/migrations/0002_data_migration.pyto copy existing data:Safety: Data migration is reversible with a
copy_data_backwardfunction.Phase 3: Cleanup (Future PR)
After verifying data integrity, old tables can be dropped.
🔗 Dependencies Handled
Required (Auto-installed)
Optional (User choice)
slack-bolt >= 1.18.0(for Slack features)External Models (Referenced, not included)
django.contrib.auth.models.User(standard Django)website.Organization(configurable via settings)website.SlackIntegration(configurable via settings)website.UserProfile(for streak tracking)Note:
DailyStatsremains inwebsiteapp as it's used for voting system too (not just Sizzle).[2]Documentation Added
README.md (
sizzle/README.md)Complete documentation including:
Configuration Guide
Added to BLT docs explaining:
Testing Checklist
Functionality Tests
Migration Tests
Configuration Tests
Management Commands
send_daily_remindersworksslack_daily_timelogsworks with Slack enabledslack_daily_timelogsfails gracefully when Slack disableddaily_checkin_reminderworkscron_send_remindersworkBackward Compatibility
Zero Breaking Changes for BLT
/sizzle/*routes)Migration Path
Existing BLT installations need only:
python manage.py migrate sizzleINSTALLED_APPS:'sizzle'(optional: can keep in existing setup)No code changes required.
Benefits
For BLT Project
For Other Projects
pip install django-sizzle(future)Summary by CodeRabbit
New Features
Documentation
Admin / UI
Chores