Context
The v3 profile page shipped with a mocked badges card (demo_badges) and a hardcoded featured
badge ({"name": "Bug Catcher", "badge": TIER_5}). Meanwhile story #2447 / PR #2517 added a
hide_badges privacy field to the edit-profile page - a field that is stored but read nowhere, so
a user who opts out still has badges rendered publicly.
This ticket connects the real badge data to the existing v3 components and closes that privacy gap.
Scope
User.get_earned_badges(include_hidden=False) - active badges, highest rank first.
Ordering must use TierRank.db_order() and only then threshold: thresholds are not comparable
across badges (a reviewer diamond needs 5, a commits silver needs 12), so sorting by threshold
would feature the wrong badge.
highest_badge, featured_badge, badges_for_display(), badge_url, to_v3_profile_dict()
fed from real data.
- Gate
hide_badges at the query source so every downstream accessor fails closed rather than
each call site remembering. Because cached_property cannot take arguments, the accessors that
need an owner-facing variant split into a method plus a cached property.
- The owner's own profile page passes
include_hidden=True.
- Rename the
demo_badges context key to profile_badges on the real profile path (the V3
examples-page fixtures in core/views.py keep the demo_* name - those are intentional).
- Fix
users/profile_cards.py, which emits a badge_url key while _user_profile.html reads
author.badge, so news post-author cards render no badge at all.
- Tests for the ordering rule, all accessors, the
hide_badges suppression, the owner bypass, and an
end-to-end profile-page render.
Out of scope
Decision to confirm with product
hide_badges semantics. Implemented as: the toggle governs what visitors see; the owner still
sees their own badges on their own profile page, because they need them visible to manage them and the
adjacent "Pick Badge" section is meaningless otherwise.
This follows the field's help_text ("Hide badges from the public profile") over its form label
("Hide badges on your profile"), which are slightly at odds. If product wants the owner's view hidden
too, it is a one-line change (drop include_hidden=True in CurrentUserProfileView), and the form
label should then win and the help_text be corrected.
Acceptance criteria
Context
The v3 profile page shipped with a mocked badges card (
demo_badges) and a hardcoded featuredbadge (
{"name": "Bug Catcher", "badge": TIER_5}). Meanwhile story #2447 / PR #2517 added ahide_badgesprivacy field to the edit-profile page - a field that is stored but read nowhere, soa user who opts out still has badges rendered publicly.
This ticket connects the real badge data to the existing v3 components and closes that privacy gap.
Scope
User.get_earned_badges(include_hidden=False)- active badges, highest rank first.Ordering must use
TierRank.db_order()and only then threshold: thresholds are not comparableacross badges (a reviewer diamond needs 5, a commits silver needs 12), so sorting by threshold
would feature the wrong badge.
highest_badge,featured_badge,badges_for_display(),badge_url,to_v3_profile_dict()fed from real data.
hide_badgesat the query source so every downstream accessor fails closed rather thaneach call site remembering. Because
cached_propertycannot take arguments, the accessors thatneed an owner-facing variant split into a method plus a cached property.
include_hidden=True.demo_badgescontext key toprofile_badgeson the real profile path (the V3examples-page fixtures in
core/views.pykeep thedemo_*name - those are intentional).users/profile_cards.py, which emits abadge_urlkey while_user_profile.htmlreadsauthor.badge, so news post-author cards render no badge at all.hide_badgessuppression, the owner bypass, and anend-to-end profile-page render.
Out of scope
featured_badgereturns the highest badge;there is no stored selection. Develop's disabled "Pick Badge" control lists tiers, not the user's
earned badges, so it needs rework rather than enabling. → gap E,
featured_badge_selection.md, and Webpage Integration: Edit Profile (Badges Dropdown) #2504.profile_badge_progress_and_states.md.hide_github_activityandhide_mailing_list_activityarestored by feat(2447): implement profile edit (visibility, acc. details, email prefs) #2517 and read nowhere. Same class of gap; they need their own ticket.
Decision to confirm with product
hide_badgessemantics. Implemented as: the toggle governs what visitors see; the owner stillsees their own badges on their own profile page, because they need them visible to manage them and the
adjacent "Pick Badge" section is meaningless otherwise.
This follows the field's
help_text("Hide badges from the public profile") over its form label("Hide badges on your profile"), which are slightly at odds. If product wants the owner's view hidden
too, it is a one-line change (drop
include_hidden=TrueinCurrentUserProfileView), and the formlabel should then win and the
help_textbe corrected.Acceptance criteria
a larger raw threshold
hide_badges=Trueshows no badges to visitors, on every accessorbadge_urlreturns""(not a placeholder medal) for a user with no badgesdemo_*naming remains on the real profile path_badges_card.html,_badge_v3.htmland
_user_profile.htmlare reusedhide_badgeson; news author cardbefore / after