-
-
Notifications
You must be signed in to change notification settings - Fork 62
Create template tag to render volunteer languages #236
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
Open
ArnavBallinCode
wants to merge
7
commits into
pyladies:main
Choose a base branch
from
ArnavBallinCode:feature/volunteer-languages-templatetag
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
5e2f93d
Create template tag to render volunteer languages
ArnavBallinCode 3707aff
Fix code formatting for volunteer template tags
ArnavBallinCode b751dd6
Address reviewer feedback: Rename and restructure template tags docum…
ArnavBallinCode 87132dd
Merge branch 'main' into feature/volunteer-languages-templatetag
ArnavBallinCode f7deaa1
Merge branch 'main' into feature/volunteer-languages-templatetag
ArnavBallinCode ab83064
Merge branch 'main' into feature/volunteer-languages-templatetag
ArnavBallinCode a79b8a2
Merge branch 'main' into feature/volunteer-languages-templatetag
ArnavBallinCode File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| # Template Tags | ||
|
|
||
| This document describes the custom template tags available across the PyLadiesCon Portal application. | ||
|
|
||
| ## Overview | ||
|
|
||
| Template tags provide reusable functionality that can be used across different templates to maintain consistency and eliminate code duplication. The portal currently includes: | ||
|
|
||
| - [Volunteer Template Tags](#volunteer-template-tags) - For rendering volunteer-related content | ||
|
|
||
| *Future sections will include sponsorship template tags, portal template tags, and other categories as they are developed.* | ||
|
|
||
| ## Volunteer Template Tags | ||
|
|
||
| ### volunteer_tags | ||
|
|
||
| The `volunteer_tags` module provides template tags for rendering volunteer profile information. | ||
|
|
||
| #### Usage | ||
|
|
||
| Load the template tags in your template: | ||
|
|
||
| ```html | ||
| {% load volunteer_tags %} | ||
| ``` | ||
|
|
||
| #### Available Tags | ||
|
|
||
| ##### `volunteer_languages_badges` | ||
|
|
||
| An inclusion tag that renders volunteer languages as Bootstrap badges. | ||
|
|
||
| **Usage:** | ||
| ```html | ||
| {% volunteer_languages_badges volunteer_profile %} | ||
| ``` | ||
|
|
||
| **With custom CSS classes:** | ||
| ```html | ||
| {% volunteer_languages_badges volunteer_profile "custom-badge-class" %} | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| - `volunteer_profile`: A VolunteerProfile instance with a language relationship | ||
| - `css_classes` (optional): Custom CSS classes for the badges (default: "badge bg-info text-dark me-1") | ||
|
|
||
| **Example:** | ||
| ```html | ||
| <!-- In your template --> | ||
| {% load volunteer_tags %} | ||
|
|
||
| <div class="languages-section"> | ||
| <h4>Languages:</h4> | ||
| {% volunteer_languages_badges object %} | ||
| </div> | ||
| ``` | ||
|
|
||
| ##### `render_volunteer_languages` | ||
|
|
||
| A simple tag that returns volunteer languages as HTML badges. | ||
|
|
||
| **Usage:** | ||
| ```html | ||
| {% render_volunteer_languages volunteer_profile %} | ||
| ``` | ||
|
|
||
| **With custom CSS classes:** | ||
| ```html | ||
| {% render_volunteer_languages volunteer_profile "my-custom-class" %} | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| - `volunteer_profile`: A VolunteerProfile instance with a language relationship | ||
| - `css_classes` (optional): Custom CSS classes for the badges (default: "badge bg-info text-dark me-1") | ||
|
|
||
| **Example:** | ||
| ```html | ||
| <!-- In your template --> | ||
| {% load volunteer_tags %} | ||
|
|
||
| <div class="volunteer-info"> | ||
| Languages: {% render_volunteer_languages volunteer_profile %} | ||
| </div> | ||
| ``` | ||
|
|
||
| #### Migration from Manual Rendering | ||
|
|
||
| ##### Before (duplicated code): | ||
| ```html | ||
| {% for language in object.language.all %} | ||
| <span class="badge bg-info text-dark me-1">{{ language.name }}</span> | ||
| {% endfor %} | ||
| ``` | ||
|
|
||
| ##### After (using template tag): | ||
| ```html | ||
| {% load volunteer_tags %} | ||
| {% volunteer_languages_badges object %} | ||
| ``` | ||
|
|
||
| #### Benefits | ||
|
|
||
| 1. **DRY Principle**: Eliminates code duplication across templates | ||
| 2. **Consistency**: Ensures consistent styling and structure | ||
| 3. **Maintainability**: Changes to language rendering only need to be made in one place | ||
| 4. **Flexibility**: Supports custom CSS classes for different use cases | ||
| 5. **Reusability**: Can be used in any template that needs to display volunteer languages |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| {% for language in languages %} | ||
| <span class="{{ css_classes }}">{{ language.name }}</span> | ||
| {% endfor %} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| from django.contrib.auth.models import User | ||
| from django.template import Context, Template | ||
| from django.test import TestCase | ||
|
|
||
| from volunteer.models import Language, VolunteerProfile | ||
|
|
||
|
|
||
| class VolunteerTemplateTagsTest(TestCase): | ||
| """Test volunteer template tags functionality.""" | ||
|
|
||
| def setUp(self): | ||
| """Set up test data.""" | ||
| self.user = User.objects.create_user( | ||
| username="testuser", email="[email protected]", password="testpass123" | ||
| ) | ||
|
|
||
| self.volunteer_profile = VolunteerProfile.objects.create( | ||
| user=self.user, availability_hours_per_week=10 | ||
| ) | ||
|
|
||
| # Create test languages | ||
| self.english = Language.objects.create(name="English", code="en") | ||
| self.spanish = Language.objects.create(name="Spanish", code="es") | ||
| self.french = Language.objects.create(name="French", code="fr") | ||
|
|
||
| # Add languages to volunteer profile | ||
| self.volunteer_profile.language.add(self.english, self.spanish) | ||
|
|
||
| def test_render_volunteer_languages_simple_tag(self): | ||
| """Test the render_volunteer_languages simple tag.""" | ||
| template = Template( | ||
| """ | ||
| {% load volunteer_tags %} | ||
| {% render_volunteer_languages volunteer_profile %} | ||
| """ | ||
| ) | ||
|
|
||
| context = Context({"volunteer_profile": self.volunteer_profile}) | ||
| rendered = template.render(context) | ||
|
|
||
| self.assertIn("English", rendered) | ||
| self.assertIn("Spanish", rendered) | ||
| self.assertIn("badge bg-info text-dark me-1", rendered) | ||
| self.assertNotIn("French", rendered) | ||
|
|
||
| def test_render_volunteer_languages_with_custom_css(self): | ||
| """Test the render_volunteer_languages simple tag with custom CSS.""" | ||
| template = Template( | ||
| """ | ||
| {% load volunteer_tags %} | ||
| {% render_volunteer_languages volunteer_profile "custom-badge" %} | ||
| """ | ||
| ) | ||
|
|
||
| context = Context({"volunteer_profile": self.volunteer_profile}) | ||
| rendered = template.render(context) | ||
|
|
||
| self.assertIn("English", rendered) | ||
| self.assertIn("Spanish", rendered) | ||
| self.assertIn("custom-badge", rendered) | ||
| self.assertNotIn("badge bg-info text-dark me-1", rendered) | ||
|
|
||
| def test_volunteer_languages_badges_inclusion_tag(self): | ||
| """Test the volunteer_languages_badges inclusion tag.""" | ||
| template = Template( | ||
| """ | ||
| {% load volunteer_tags %} | ||
| {% volunteer_languages_badges volunteer_profile %} | ||
| """ | ||
| ) | ||
|
|
||
| context = Context({"volunteer_profile": self.volunteer_profile}) | ||
| rendered = template.render(context) | ||
|
|
||
| self.assertIn("English", rendered) | ||
| self.assertIn("Spanish", rendered) | ||
| self.assertIn("badge bg-info text-dark me-1", rendered) | ||
| self.assertNotIn("French", rendered) | ||
|
|
||
| def test_volunteer_languages_badges_with_custom_css(self): | ||
| """Test the volunteer_languages_badges inclusion tag with custom CSS.""" | ||
| template = Template( | ||
| """ | ||
| {% load volunteer_tags %} | ||
| {% volunteer_languages_badges volunteer_profile "custom-style" %} | ||
| """ | ||
| ) | ||
|
|
||
| context = Context({"volunteer_profile": self.volunteer_profile}) | ||
| rendered = template.render(context) | ||
|
|
||
| self.assertIn("English", rendered) | ||
| self.assertIn("Spanish", rendered) | ||
| self.assertIn("custom-style", rendered) | ||
| self.assertNotIn("badge bg-info text-dark me-1", rendered) | ||
|
|
||
| def test_template_tags_with_no_languages(self): | ||
| """Test template tags when volunteer has no languages.""" | ||
| # Create volunteer with no languages | ||
| user2 = User.objects.create_user( | ||
| username="testuser2", email="[email protected]", password="testpass123" | ||
| ) | ||
| volunteer_profile2 = VolunteerProfile.objects.create( | ||
| user=user2, availability_hours_per_week=5 | ||
| ) | ||
|
|
||
| template = Template( | ||
| """ | ||
| {% load volunteer_tags %} | ||
| {% render_volunteer_languages volunteer_profile %} | ||
| """ | ||
| ) | ||
|
|
||
| context = Context({"volunteer_profile": volunteer_profile2}) | ||
| rendered = template.render(context) | ||
|
|
||
| # Should render empty string when no languages | ||
| self.assertEqual(rendered.strip(), "") | ||
|
|
||
| def test_template_tags_with_none_profile(self): | ||
| """Test template tags when volunteer_profile is None.""" | ||
| template = Template( | ||
| """ | ||
| {% load volunteer_tags %} | ||
| {% render_volunteer_languages volunteer_profile %} | ||
| """ | ||
| ) | ||
|
|
||
| context = Context({"volunteer_profile": None}) | ||
| rendered = template.render(context) | ||
|
|
||
| # Should render empty string when profile is None | ||
| self.assertEqual(rendered.strip(), "") | ||
|
|
||
| def test_template_tags_with_missing_profile(self): | ||
| """Test template tags when volunteer_profile is not in context.""" | ||
| template = Template( | ||
| """ | ||
| {% load volunteer_tags %} | ||
| {% render_volunteer_languages volunteer_profile %} | ||
| """ | ||
| ) | ||
|
|
||
| context = Context({}) | ||
| rendered = template.render(context) | ||
|
|
||
| # Should render empty string when profile is missing | ||
| self.assertEqual(rendered.strip(), "") |
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| from django import template | ||
| from django.utils.safestring import mark_safe | ||
|
|
||
| register = template.Library() | ||
|
|
||
|
|
||
| @register.simple_tag | ||
| def render_volunteer_languages( | ||
| volunteer_profile, css_classes="badge bg-info text-dark me-1" | ||
| ): | ||
| """ | ||
| Renders volunteer languages as badges. | ||
|
|
||
| Args: | ||
| volunteer_profile: VolunteerProfile instance with language relationship | ||
| css_classes: CSS classes for the badge styling (optional) | ||
|
|
||
| Returns: | ||
| Safe HTML string with language badges | ||
| """ | ||
| if not volunteer_profile or not hasattr(volunteer_profile, "language"): | ||
| return "" | ||
|
|
||
| languages = volunteer_profile.language.all() | ||
| if not languages: | ||
| return "" | ||
|
|
||
| badge_html = [] | ||
| for language in languages: | ||
| badge_html.append(f'<span class="{css_classes}">{language.name}</span>') | ||
|
|
||
| return mark_safe(" ".join(badge_html)) | ||
|
|
||
|
|
||
| @register.inclusion_tag("volunteer/templatetags/volunteer_languages.html") | ||
| def volunteer_languages_badges( | ||
| volunteer_profile, css_classes="badge bg-info text-dark me-1" | ||
| ): | ||
| """ | ||
| Inclusion tag to render volunteer languages using a template. | ||
|
|
||
| Args: | ||
| volunteer_profile: VolunteerProfile instance with language relationship | ||
| css_classes: CSS classes for the badge styling (optional) | ||
|
|
||
| Returns: | ||
| Context dictionary for the template | ||
| """ | ||
| languages = [] | ||
| if volunteer_profile and hasattr(volunteer_profile, "language"): | ||
| languages = volunteer_profile.language.all() | ||
|
|
||
| return { | ||
| "languages": languages, | ||
| "css_classes": css_classes, | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.