Skip to content

Commit

Permalink
Merge pull request #52 from Stormheg/support/wagtail42
Browse files Browse the repository at this point in the history
Wagtail 4.1 and 4.2 support (revised)
  • Loading branch information
Stormheg authored Oct 5, 2023
2 parents 79b0390 + 8211e64 commit fa35ddd
Show file tree
Hide file tree
Showing 28 changed files with 649 additions and 238 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Wagtail 4.2 compatibility
- Wagtail 4.1 compatibility
- NO SUPPORT for Wagtail 4.0 and older, sorry

## [0.7] - 2022-03-31

- [Add default_auto_field](https://github.com/torchbox/wagtail-ab-testing/pull/42)
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Key features:

## Usage

Wagtail A/B Testing works with Django 3.2+, Wagtail 4.1+ on Python 3.7+ environments.

### Creating an A/B test

Any user with the "Create A/B test" permission can create an A/B test by clicking "Save and create A/B test" from the page's action menu.
Expand Down Expand Up @@ -72,7 +74,7 @@ from wagtail_ab_testing import urls as ab_testing_urls
urlpatterns = [
...

url(r'^abtesting/', include(ab_testing_urls)),
path('abtesting/', include(ab_testing_urls)),
]
```

Expand All @@ -99,7 +101,7 @@ add your goal type to the list of options shown to users when they create A/B te
```python
# myapp/wagtail_hooks.py

from wagtail.core import hooks
from wagtail import hooks
from wagtail_ab_testing.events import BaseEvent


Expand Down Expand Up @@ -143,7 +145,7 @@ Firstly, we need to register the event type. To do this, implement a handler for
```python
# myapp/wagtail_hooks.py

from wagtail.core import hooks
from wagtail import hooks
from wagtail_ab_testing.events import BaseEvent

from .models import ContactUsFormPage
Expand Down
17 changes: 9 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,23 @@
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Framework :: Django",
"Framework :: Django :: 2.2",
"Framework :: Django :: 3.0",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.0",
"Framework :: Django :: 4.1",
"Framework :: Wagtail",
"Framework :: Wagtail :: 2",
"Framework :: Wagtail :: 4",
],
install_requires=[
"Django>=2.2,<3.3",
"Wagtail>=2.11,<2.17",
"Wagtail>=4.1",
"user-agents>=2.2,<2.3",
"numpy>=1.19.4,<1.20",
"scipy>=1.5.4,<1.6",
"numpy>=1.19.4,<1.25",
"scipy>=1.5.4,<1.10",
],
extras_require={
"testing": ["dj-database-url==0.5.0", "freezegun==0.3.15"],
"testing": ["dj-database-url==0.5.0", "freezegun==1.2.1"],
},
zip_safe=False,
)
4 changes: 2 additions & 2 deletions testmanage.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

from django.core.management import execute_from_command_line

from wagtail.test.settings import STATIC_ROOT, MEDIA_ROOT


os.environ["DJANGO_SETTINGS_MODULE"] = "wagtail_ab_testing.test.settings"

Expand Down Expand Up @@ -56,8 +58,6 @@ def runtests():
try:
execute_from_command_line(argv)
finally:
from wagtail.tests.settings import STATIC_ROOT, MEDIA_ROOT

shutil.rmtree(STATIC_ROOT, ignore_errors=True)
shutil.rmtree(MEDIA_ROOT, ignore_errors=True)

Expand Down
20 changes: 12 additions & 8 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
skipsdist = True
usedevelop = True

envlist = py{37,38,39}-dj{22,30,32,main}-wa{211,215,216,main}-{sqlite,postgres}
envlist =
py{37,38,39,310}-dj{32,40,41}-wa{41,42}-{sqlite,postgres}
py{311}-dj{41}-wa{41,42,main}-{sqlite,postgres}

[flake8]
# E501: Line too long
Expand All @@ -17,26 +19,28 @@ commands = coverage run testmanage.py test --deprecation all
basepython =
py37: python3.7
py38: python3.8
py39: python3.9
py310: python3.10
py311: python3.11

deps =
coverage

dj22: Django>=2.2,<2.3
dj30: Django>=3.0,<3.1
dj32: Django>=3.2,<3.3
dj40: Django>=4.0,<4.1
dj41: Django>=4.1,<4.2
djmain: git+https://github.com/django/django.git@main#egg=Django

wa211: wagtail>=2.11,<2.12
wa215: wagtail>=2.15rc1,<2.16
wa216: wagtail>=2.16.1,<2.17
wa41: wagtail>=4.1,<4.2
wa42: wagtail>=4.2,<5.0
wamain: git+https://github.com/wagtail/wagtail.git

postgres: psycopg2==2.8.6
postgres: psycopg2==2.9.3

setenv =
postgres: DATABASE_URL=postgres:///wagtail_ab_testing

[testenv:flake8]
basepython=python3.7
basepython=python3.11
deps=flake8>=2.2.0
commands=flake8 wagtail_ab_testing
1 change: 0 additions & 1 deletion wagtail_ab_testing/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
default_app_config = "wagtail_ab_testing.apps.WagtailAbTestingAppConfig"
5 changes: 3 additions & 2 deletions wagtail_ab_testing/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from rest_framework import fields, routers, serializers, status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from wagtail.core.models import Page, Site

from wagtail.models import Page, Site

from .models import AbTest

Expand Down Expand Up @@ -64,7 +65,7 @@ def serve_variant(self, request, pk=None):
test = self.get_object()
request.wagtail_ab_testing_test = test
request.wagtail_ab_testing_serving_variant = True
return test.variant_revision.as_page_object().serve(request)
return test.variant_revision.as_object().serve(request)

@action(detail=True, methods=['post'])
def add_participant(self, request, pk=None):
Expand Down
2 changes: 1 addition & 1 deletion wagtail_ab_testing/events.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.utils.translation import gettext_lazy as __

from wagtail.core import hooks
from wagtail import hooks


class BaseEvent:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Generated by Django 4.2.2 on 2023-06-18 11:26

# PURPOSE OF THIS MIGRATION
#
# This squashed migration was created for compatibility with Wagtail 4.0's migration from PageRevision
# to a generic Revision model. The `0001_initial` migration in this project must continue to reference the old
# PageRevision model and wagtailcore.0052_pagelogentry dependency to maintain a consistent migration history
# for existing databases. On the flip side, new projects that run wagtail_ab_testing's migrations for the first time
# will encounter a PageRevision model that no longer exists which causes errors.
#
# The solution for new projects is to use this squashed migration file instead.
# This file contains no references to PageRevision and will migrate without errors.

import datetime
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.migrations.operations.special
import django.db.models.deletion


# Migrated from wagtail_ab_testing.migrations.0007_grant_moderators_add_abtest_permission
def grant_moderators_add_abtest_permission(apps, schema_editor):
ContentType = apps.get_model("contenttypes.ContentType")
Permission = apps.get_model("auth.Permission")
Group = apps.get_model("auth.Group")

abtest_content_type, created = ContentType.objects.get_or_create(
app_label="wagtail_ab_testing", model="abtest"
)
add_abtest_permission, created = Permission.objects.get_or_create(
content_type=abtest_content_type, codename="add_abtest"
)

moderators_group = Group.objects.filter(name="Moderators").first()
if moderators_group:
moderators_group.permissions.add(add_abtest_permission)


class Migration(migrations.Migration):
replaces = [
("wagtail_ab_testing", "0001_initial"),
("wagtail_ab_testing", "0002_abtesthourlylog"),
("wagtail_ab_testing", "0003_abtest_winning_variant"),
("wagtail_ab_testing", "0004_started_at_and_duration"),
("wagtail_ab_testing", "0005_hypothesis_and_created_by"),
("wagtail_ab_testing", "0006_sample_size_min_value"),
("wagtail_ab_testing", "0007_grant_moderators_add_abtest_permission"),
("wagtail_ab_testing", "0008_finished_status"),
("wagtail_ab_testing", "0009_rename_variant_to_version"),
("wagtail_ab_testing", "0010_rename_treatment_to_variant"),
("wagtail_ab_testing", "0011_rename_treatment_to_variant_data"),
("wagtail_ab_testing", "0012_abtest_variant_revision"),
]

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("wagtailcore", "0078_referenceindex"),
]

operations = [
migrations.CreateModel(
name="AbTest",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255)),
("goal_event", models.CharField(max_length=255)),
(
"sample_size",
models.PositiveIntegerField(
validators=[django.core.validators.MinValueValidator(1)]
),
),
(
"status",
models.CharField(
choices=[
("draft", "Draft"),
("running", "Running"),
("paused", "Paused"),
("cancelled", "Cancelled"),
("finished", "Finished"),
("completed", "Completed"),
],
default="draft",
max_length=20,
),
),
(
"goal_page",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to="wagtailcore.page",
),
),
(
"page",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="ab_tests",
to="wagtailcore.page",
),
),
(
"variant_revision",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="wagtailcore.revision",
),
),
(
"winning_version",
models.CharField(
choices=[("control", "Control"), ("variant", "Variant")],
max_length=9,
null=True,
),
),
("current_run_started_at", models.DateTimeField(null=True)),
("first_started_at", models.DateTimeField(null=True)),
(
"previous_run_duration",
models.DurationField(default=datetime.timedelta(0)),
),
(
"created_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to=settings.AUTH_USER_MODEL,
),
),
("hypothesis", models.TextField(blank=True)),
],
),
migrations.CreateModel(
name="AbTestHourlyLog",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"version",
models.CharField(
choices=[("control", "Control"), ("variant", "Variant")],
max_length=9,
),
),
("date", models.DateField()),
("hour", models.PositiveSmallIntegerField()),
("participants", models.PositiveIntegerField(default=0)),
("conversions", models.PositiveIntegerField(default=0)),
(
"ab_test",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="hourly_logs",
to="wagtail_ab_testing.abtest",
),
),
],
options={"ordering": ["ab_test", "version", "date", "hour"]},
),
migrations.AlterUniqueTogether(
name="abtesthourlylog",
unique_together={("ab_test", "version", "date", "hour")},
),
migrations.RunPython(
code=grant_moderators_add_abtest_permission,
reverse_code=django.db.migrations.operations.special.RunPython.noop,
),
]
20 changes: 20 additions & 0 deletions wagtail_ab_testing/migrations/0012_abtest_variant_revision.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 4.1.6 on 2023-03-02 13:34

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('wagtailcore', '0078_referenceindex'),
('wagtail_ab_testing', '0011_rename_treatment_to_variant_data'),
]

operations = [
migrations.AlterField(
model_name='abtest',
name='variant_revision',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='wagtailcore.revision'),
),
]
Loading

0 comments on commit fa35ddd

Please sign in to comment.