diff --git a/adserver/analyzer/migrations/0008_migrate_jsonfield.py b/adserver/analyzer/migrations/0008_migrate_jsonfield.py new file mode 100644 index 00000000..152d935c --- /dev/null +++ b/adserver/analyzer/migrations/0008_migrate_jsonfield.py @@ -0,0 +1,34 @@ +# Generated by Django 5.0.8 on 2024-09-30 21:04 + +import adserver.analyzer.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("adserver_analyzer", "0007_add_advertiser_flights"), + ] + + operations = [ + migrations.AlterField( + model_name="analyzedadvertiserurl", + name="keywords", + field=models.JSONField( + blank=True, + null=True, + validators=[adserver.analyzer.validators.KeywordsValidator()], + verbose_name="Keywords for this URL", + ), + ), + migrations.AlterField( + model_name="analyzedurl", + name="keywords", + field=models.JSONField( + blank=True, + null=True, + validators=[adserver.analyzer.validators.KeywordsValidator()], + verbose_name="Keywords for this URL", + ), + ), + ] diff --git a/adserver/analyzer/models.py b/adserver/analyzer/models.py index 1f682d5f..a269ab7d 100644 --- a/adserver/analyzer/models.py +++ b/adserver/analyzer/models.py @@ -3,7 +3,6 @@ from django.db import models from django.utils.translation import gettext_lazy as _ from django_extensions.db.models import TimeStampedModel -from jsonfield import JSONField from ..models import Advertiser from ..models import Flight @@ -21,7 +20,7 @@ class BaseAnalyzedUrl(TimeStampedModel): ) # Fields below are updated by the analyzer - keywords = JSONField( + keywords = models.JSONField( _("Keywords for this URL"), blank=True, null=True, diff --git a/adserver/forms.py b/adserver/forms.py index bf7ee1af..829cc3c5 100644 --- a/adserver/forms.py +++ b/adserver/forms.py @@ -28,7 +28,6 @@ from django.utils.text import slugify from django.utils.translation import gettext from django.utils.translation import gettext_lazy as _ -from simple_history.utils import update_change_reason from .models import Advertisement from .models import Campaign @@ -1358,7 +1357,8 @@ def save(self, commit=True): user.invite_user() # Track who added this user - update_change_reason(user, "Invited via authorized users view") + # See: https://github.com/jazzband/django-simple-history/issues/1181 + # update_change_reason(user, "Invited via authorized users view") # You will need to add the user to the publisher/advertiser in the view return user diff --git a/adserver/migrations/0097_migrate_jsonfield.py b/adserver/migrations/0097_migrate_jsonfield.py new file mode 100644 index 00000000..e264d0de --- /dev/null +++ b/adserver/migrations/0097_migrate_jsonfield.py @@ -0,0 +1,110 @@ +# Generated by Django 5.0.8 on 2024-09-30 21:04 + +import adserver.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("adserver", "0096_simple_history_upgrade"), + ] + + operations = [ + migrations.AlterField( + model_name="click", + name="keywords", + field=models.JSONField( + blank=True, null=True, verbose_name="Keyword targeting for this view" + ), + ), + migrations.AlterField( + model_name="flight", + name="targeting_parameters", + field=models.JSONField( + blank=True, + null=True, + validators=[adserver.validators.TargetingParametersValidator()], + verbose_name="Targeting parameters", + ), + ), + migrations.AlterField( + model_name="flight", + name="traffic_cap", + field=models.JSONField( + blank=True, + default=None, + null=True, + validators=[adserver.validators.TrafficFillValidator()], + verbose_name="Traffic cap", + ), + ), + migrations.AlterField( + model_name="flight", + name="traffic_fill", + field=models.JSONField( + blank=True, + default=None, + null=True, + validators=[adserver.validators.TrafficFillValidator()], + verbose_name="Traffic fill", + ), + ), + migrations.AlterField( + model_name="historicalflight", + name="targeting_parameters", + field=models.JSONField( + blank=True, + null=True, + validators=[adserver.validators.TargetingParametersValidator()], + verbose_name="Targeting parameters", + ), + ), + migrations.AlterField( + model_name="historicalflight", + name="traffic_cap", + field=models.JSONField( + blank=True, + default=None, + null=True, + validators=[adserver.validators.TrafficFillValidator()], + verbose_name="Traffic cap", + ), + ), + migrations.AlterField( + model_name="historicalflight", + name="traffic_fill", + field=models.JSONField( + blank=True, + default=None, + null=True, + validators=[adserver.validators.TrafficFillValidator()], + verbose_name="Traffic fill", + ), + ), + migrations.AlterField( + model_name="offer", + name="keywords", + field=models.JSONField( + blank=True, null=True, verbose_name="Keyword targeting for this view" + ), + ), + migrations.AlterField( + model_name="region", + name="prices", + field=models.JSONField( + blank=True, + help_text="Topic pricing matrix for this region", + null=True, + validators=[adserver.validators.TopicPricingValidator()], + verbose_name="Topic prices", + ), + ), + migrations.AlterField( + model_name="view", + name="keywords", + field=models.JSONField( + blank=True, null=True, verbose_name="Keyword targeting for this view" + ), + ), + ] diff --git a/adserver/models.py b/adserver/models.py index 9e54d74a..35444fa1 100644 --- a/adserver/models.py +++ b/adserver/models.py @@ -33,7 +33,6 @@ from django_countries.fields import CountryField from django_extensions.db.models import TimeStampedModel from djstripe.enums import InvoiceStatus -from jsonfield import JSONField from simple_history.models import HistoricalRecords from user_agents import parse @@ -195,7 +194,7 @@ class Region(TimeStampedModel, models.Model): help_text=_("Whether advertisers can select this region for new flights"), ) - prices = JSONField( + prices = models.JSONField( _("Topic prices"), blank=True, null=True, @@ -831,7 +830,7 @@ class Flight(TimeStampedModel, IndestructibleModel): Campaign, related_name="flights", on_delete=models.PROTECT ) - targeting_parameters = JSONField( + targeting_parameters = models.JSONField( _("Targeting parameters"), blank=True, null=True, @@ -866,7 +865,7 @@ class Flight(TimeStampedModel, IndestructibleModel): # "countries": {"US": 0.1, "CA": 0.05, "DE": 0.05}, # "regions": {"us-ca": 0.25, "eu": 0.5}, # } - traffic_fill = JSONField( + traffic_fill = models.JSONField( _("Traffic fill"), blank=True, null=True, @@ -877,7 +876,7 @@ class Flight(TimeStampedModel, IndestructibleModel): # If set, any publisher, country, or region whose `traffic_fill` exceeds the cap # will not be eligible to show on this campaign until they're below the cap. # Format is the same as `traffic_fill` but this is set manually - traffic_cap = JSONField( + traffic_cap = models.JSONField( _("Traffic cap"), blank=True, null=True, @@ -2540,7 +2539,9 @@ class AdBase(TimeStampedModel, IndestructibleModel): ) # Client data - keywords = JSONField(_("Keyword targeting for this view"), blank=True, null=True) + keywords = models.JSONField( + _("Keyword targeting for this view"), blank=True, null=True + ) div_id = models.CharField( _("Div id"), blank=True, null=True, max_length=DIV_MAXLENGTH ) diff --git a/adserver/staff/forms.py b/adserver/staff/forms.py index d8c60571..e942348f 100644 --- a/adserver/staff/forms.py +++ b/adserver/staff/forms.py @@ -17,7 +17,6 @@ from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ from djstripe.models import Customer -from simple_history.utils import update_change_reason from ..constants import EMAILED from ..constants import PUBLISHER_HOUSE_CAMPAIGN @@ -110,7 +109,10 @@ def create_user(self): user_email = self.cleaned_data["user_email"] user = User.objects.create_user(name=user_name, email=user_email, password="") - update_change_reason(user, self.message) + + # See: https://github.com/jazzband/django-simple-history/issues/1181 + # update_change_reason(user, self.message) + if hasattr(user, "invite_user"): user.invite_user() return user @@ -134,7 +136,7 @@ def create_advertiser(self): campaign.publisher_groups.add(pub_group) flight_name = f"{advertiser_name} Initial Flight" - flight = Flight.objects.create( + Flight.objects.create( campaign=campaign, name=flight_name, slug=slugify(flight_name), @@ -145,9 +147,10 @@ def create_advertiser(self): }, ) - update_change_reason(advertiser, self.message) - update_change_reason(campaign, self.message) - update_change_reason(flight, self.message) + # See https://github.com/jazzband/django-simple-history/issues/1181 + # update_change_reason(advertiser, self.message) + # update_change_reason(campaign, self.message) + # update_change_reason(flight, self.message) return advertiser @@ -256,7 +259,10 @@ def create_user(self): user_email = self.cleaned_data["user_email"] user = User.objects.create_user(name=user_name, email=user_email, password="") - update_change_reason(user, self.message) + + # See https://github.com/jazzband/django-simple-history/issues/1181 + # update_change_reason(user, self.message) + if hasattr(user, "invite_user"): user.invite_user() return user @@ -277,7 +283,8 @@ def create_publisher(self): if group_obj: group_obj.publishers.add(publisher) - update_change_reason(publisher, self.message) + # See: https://github.com/jazzband/django-simple-history/issues/1181 + # update_change_reason(publisher, self.message) # Create this publisher's advertiser account self.create_publisher_advertiser_account(publisher) @@ -305,7 +312,7 @@ def create_publisher_advertiser_account(self, publisher): campaign.publisher_groups.add(pub_group) flight_name = f"{publisher.name} House Ads" - flight = Flight.objects.create( + Flight.objects.create( campaign=campaign, name=flight_name, slug=slugify(flight_name), @@ -316,9 +323,10 @@ def create_publisher_advertiser_account(self, publisher): }, ) - update_change_reason(advertiser, self.message) - update_change_reason(campaign, self.message) - update_change_reason(flight, self.message) + # See: https://github.com/jazzband/django-simple-history/issues/1181 + # update_change_reason(advertiser, self.message) + # update_change_reason(campaign, self.message) + # update_change_reason(flight, self.message) def save(self): """Create the publisher and associated objects. Send the invitation to the user account.""" @@ -408,6 +416,7 @@ def save(self): status=EMAILED, ) - update_change_reason(payout, "Payout via staff interface") + # See: https://github.com/jazzband/django-simple-history/issues/1181 + # update_change_reason(payout, "Payout via staff interface") return payout diff --git a/adserver/tasks.py b/adserver/tasks.py index 5356959e..ead9638d 100644 --- a/adserver/tasks.py +++ b/adserver/tasks.py @@ -18,7 +18,6 @@ from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ from django_slack import slack_message -from simple_history.utils import update_change_reason from config.celery_app import app @@ -886,9 +885,10 @@ def notify_of_completed_flights(): flight.save() # Store the change reason in the history - update_change_reason( - flight, f"Hard stopped with ${value_remaining} value remaining." - ) + # See: https://github.com/jazzband/django-simple-history/issues/1181 + # update_change_reason( + # flight, f"Hard stopped with ${value_remaining} value remaining." + # ) completed_flights_by_advertiser[flight.campaign.advertiser.slug].append( flight diff --git a/requirements/base.in b/requirements/base.in index 69566dab..75a1348f 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -44,7 +44,6 @@ IP2Proxy # Countries helper used in ad targeting django-countries -jsonfield bleach # Security features @@ -62,3 +61,6 @@ PyJWT # CORS headers django-cors-headers + +# Deprecated, but still used in migrations +jsonfield