-
Notifications
You must be signed in to change notification settings - Fork 618
Benefit Features db modeling #1813
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
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
28c21a9
Move manager to managers.py
berinhard 0c390d4
Add docstrings to help with models understanding
berinhard cc9d919
Draft of a command to generate the sponsors.csv
berinhard e43e625
Add django-polymorphic as a dependency
berinhard a0851b1
Introduce polymorphic models
berinhard 1c204b9
Display benefit feature as stacked inline at benefit admin page
berinhard 6e5e203
Remove logo placements that aren't necessary to be tracked
berinhard d7b2296
Fixes for an initial draft on the command to output the CSV
berinhard 046cadc
Sponsorship benefit related models should be use to configure the fea…
berinhard 8f8ac5b
Create benefit feature models
berinhard b0b63d1
Create base method to generate a valid BenefitFeature from a BenefitF…
berinhard facfba5
Add benefit features to SponsorBenefit at creation time
berinhard 02e2427
Method to create a new sponsors and, thus, sponsor benefits/features …
berinhard 8c591f9
Move polymorphic dependency to correct settings
berinhard e877127
Remove old TODO comment
berinhard 1afafbc
Use previous versions from django-polymorphic
berinhard 7519428
Add missing date update when sponsorship is finalized
berinhard 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 |
---|---|---|
|
@@ -43,3 +43,4 @@ django-countries==6.1.3 | |
xhtml2pdf==0.2.5 | ||
django-easy-pdf==0.1.1 | ||
num2words==0.5.10 | ||
django-polymorphic==2.1.2 |
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 |
---|---|---|
|
@@ -191,6 +191,7 @@ | |
'rest_framework', | ||
'rest_framework.authtoken', | ||
'django_filters', | ||
'polymorphic', | ||
] | ||
|
||
# Fixtures | ||
|
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,18 @@ | ||
from enum import Enum | ||
|
||
|
||
class LogoPlacementChoices(Enum): | ||
SIDEBAR = "sidebar" | ||
SPONSORS_PAGE = "sponsors" | ||
JOBS = "jobs" | ||
BLOG = "blogpost" | ||
FOOTER = "footer" | ||
DOCS = "docs" | ||
DOWNLOAD_PAGE = "download" | ||
DEV_GUIDE = "devguide" | ||
|
||
class PublisherChoices(Enum): | ||
FOUNDATION = "psf" | ||
PYCON = "pycon" | ||
PYPI = "pypi" | ||
CORE_DEV = "core" | ||
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,89 @@ | ||
import csv | ||
from django.core.management import BaseCommand | ||
from django.template.defaultfilters import slugify | ||
|
||
from sponsors.models import Sponsorship, Contract | ||
|
||
# This command works as a faster entrypoint to generate a CSV file | ||
# with all the sponsor data required by the sponsor placement server | ||
# Python.org will use to display sponsors' logo. This command can | ||
# become an optional one once such operation is enabled via admin. | ||
|
||
class Command(BaseCommand): | ||
""" | ||
Generate CSV with sponsors data to be sent to sponsor placement server | ||
""" | ||
help = "Generate CSV with sponsors data to be sent to sponsor placement server" | ||
|
||
def handle(self, **options): | ||
qs = Sponsorship.objects.finalized().select_related('sponsor') | ||
if not qs.exists(): | ||
print("There's no finalized Sponsorship.") | ||
return | ||
|
||
rows = [] | ||
for sponsorship in qs.iterator(): | ||
base_row = { | ||
"sponsor": sponsorship.sponsor.name, | ||
"description": sponsorship.sponsor.description, | ||
"logo": sponsorship.sponsor.web_logo.url, | ||
"sponsor_url": sponsorship.sponsor.landing_page_url, | ||
"start_date": sponsorship.start_date.isoformat(), | ||
"end_date": sponsorship.end_date.isoformat(), | ||
} | ||
|
||
benefits = sponsorship.benefits.select_related('sponsorship_benefit') | ||
for benefit in benefits.iterator(): | ||
# TODO implement this as DB objects not hardcoded checks | ||
# - check for logo placements | ||
# - use the program to determine the publisher | ||
# - use the flight to determine the placement (footer/sidebar/sponsor etc) | ||
flight_mapping = { | ||
# Foundation | ||
"Logo on python.org": "sponsors", | ||
"jobs.python.org support": "jobs", | ||
"Logo listed on PSF blog": "blogspot", | ||
# Pycon | ||
"PyCon website Listing": "sponsors", | ||
# Pypi | ||
"Logo on the PyPI sponsors page": "sponsors", | ||
"Logo in a prominent position on the PyPI project detail page": "sidebar", | ||
"Logo on the PyPI footer": "footer", | ||
# Core dev | ||
"docs.python.org recognition": "docs", | ||
"Logo on python.org/downloads/": "docs-download", | ||
"Logo recognition on devguide.python.org/": "devguide" | ||
} | ||
|
||
publisher = benefit.program.name | ||
flight = flight_mapping.get(benefit.name) | ||
if publisher and flight: | ||
row = base_row.copy() | ||
|
||
if not sponsorship.sponsor.web_logo: | ||
print(f"WARNING: sponsor {sponsorship.sponsor} without logo") | ||
continue | ||
|
||
if publisher == "Foundation" and flight in ["jobs", "blogspot"]: | ||
row["sponsor_url"] = "https://www.python.org/psf/sponsorship/sponsors/" | ||
|
||
row["publisher"] = publisher | ||
row["flight"] = slugify(publisher) + '-' + flight | ||
rows.append(row) | ||
|
||
columns = [ | ||
"publisher", | ||
"flight", | ||
"sponsor", | ||
"description", | ||
"logo", | ||
"start_date", | ||
"end_date", | ||
"sponsor_url", | ||
] | ||
with open('sponsors.csv', 'w') as fd: | ||
writer = csv.DictWriter(fd, fieldnames=columns) | ||
writer.writeheader() | ||
writer.writerows(rows) | ||
|
||
print(f"Done!") |
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,48 @@ | ||
# Generated by Django 2.0.13 on 2021-07-15 20:15 | ||
|
||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('contenttypes', '0002_remove_content_type_name'), | ||
('sponsors', '0028_auto_20210707_1426'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='BenefitFeatureConfiguration', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
], | ||
options={ | ||
'verbose_name': 'Benefit Feature Configuration', | ||
'verbose_name_plural': 'Benefit Feature Configurations', | ||
}, | ||
), | ||
migrations.CreateModel( | ||
name='LogoPlacementConfiguration', | ||
fields=[ | ||
('benefitfeatureconfiguration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='sponsors.BenefitFeatureConfiguration')), | ||
('publisher', models.CharField(choices=[('psf', 'Foundation'), ('pycon', 'Pycon'), ('pypi', 'Pypi'), ('core', 'Core Dev')], help_text='On which site should the logo be displayed?', max_length=30, verbose_name='Publisher')), | ||
('logo_place', models.CharField(choices=[('sidebar', 'Sidebar'), ('sponsors', 'Sponsors Page'), ('jobs', 'Jobs'), ('blogpost', 'Blog'), ('footer', 'Footer'), ('docs', 'Docs'), ('download', 'Download Page'), ('devguide', 'Dev Guide')], help_text='Where the logo should be placed?', max_length=30, verbose_name='Logo Placement')), | ||
], | ||
options={ | ||
'verbose_name': 'Logo Placement Configuration', | ||
'verbose_name_plural': 'Logo Placement Configurations', | ||
}, | ||
bases=('sponsors.benefitfeatureconfiguration',), | ||
), | ||
migrations.AddField( | ||
model_name='benefitfeatureconfiguration', | ||
name='benefit', | ||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sponsors.SponsorshipBenefit'), | ||
), | ||
migrations.AddField( | ||
model_name='benefitfeatureconfiguration', | ||
name='polymorphic_ctype', | ||
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_sponsors.benefitfeatureconfiguration_set+', to='contenttypes.ContentType'), | ||
), | ||
] |
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,54 @@ | ||
# Generated by Django 2.0.13 on 2021-07-15 20:23 | ||
|
||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('contenttypes', '0002_remove_content_type_name'), | ||
('sponsors', '0029_auto_20210715_2015'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='BenefitFeature', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
], | ||
options={ | ||
'verbose_name': 'Benefit Feature', | ||
'verbose_name_plural': 'Benefit Features', | ||
}, | ||
), | ||
migrations.AlterModelOptions( | ||
name='logoplacementconfiguration', | ||
options={'base_manager_name': 'objects', 'verbose_name': 'Logo Placement Configuration', 'verbose_name_plural': 'Logo Placement Configurations'}, | ||
), | ||
migrations.CreateModel( | ||
name='LogoPlacement', | ||
fields=[ | ||
('benefitfeature_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='sponsors.BenefitFeature')), | ||
('publisher', models.CharField(choices=[('psf', 'Foundation'), ('pycon', 'Pycon'), ('pypi', 'Pypi'), ('core', 'Core Dev')], help_text='On which site should the logo be displayed?', max_length=30, verbose_name='Publisher')), | ||
('logo_place', models.CharField(choices=[('sidebar', 'Sidebar'), ('sponsors', 'Sponsors Page'), ('jobs', 'Jobs'), ('blogpost', 'Blog'), ('footer', 'Footer'), ('docs', 'Docs'), ('download', 'Download Page'), ('devguide', 'Dev Guide')], help_text='Where the logo should be placed?', max_length=30, verbose_name='Logo Placement')), | ||
], | ||
options={ | ||
'verbose_name': 'Logo Placement', | ||
'verbose_name_plural': 'Logo Placement', | ||
'abstract': False, | ||
'base_manager_name': 'objects', | ||
}, | ||
bases=('sponsors.benefitfeature', models.Model), | ||
), | ||
migrations.AddField( | ||
model_name='benefitfeature', | ||
name='polymorphic_ctype', | ||
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_sponsors.benefitfeature_set+', to='contenttypes.ContentType'), | ||
), | ||
migrations.AddField( | ||
model_name='benefitfeature', | ||
name='sponsor_benefit', | ||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sponsors.SponsorBenefit'), | ||
), | ||
] |
Oops, something went wrong.
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.
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.
We have other choice fields in the sponsors app, such as sponsorship's status or contract's status. For the sake of integrity, I'd like to refactor them to also use
Enum
too if you think it's a good idea.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.
yes! i think this is a wonderful idea!