django-beta 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- beta/__init__.py +1 -0
- beta/admin.py +12 -0
- beta/apps.py +11 -0
- beta/forms.py +26 -0
- beta/listeners.py +17 -0
- beta/managers.py +15 -0
- beta/migrations/0001_initial.py +29 -0
- beta/migrations/__init__.py +0 -0
- beta/models.py +29 -0
- beta/templates/beta/confirmation.html +3 -0
- beta/templates/beta/signup.html +5 -0
- beta/urls.py +8 -0
- beta/views.py +20 -0
- django_beta-0.2.0.dist-info/METADATA +102 -0
- django_beta-0.2.0.dist-info/RECORD +18 -0
- django_beta-0.2.0.dist-info/WHEEL +4 -0
- django_beta-0.2.0.dist-info/licenses/AUTHORS.txt +1 -0
- django_beta-0.2.0.dist-info/licenses/LICENSE.txt +27 -0
beta/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = (0, 1, 0)
|
beta/admin.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
|
|
3
|
+
from beta.models import BetaSignup
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BetaSignupAdmin(admin.ModelAdmin):
|
|
7
|
+
model = BetaSignup
|
|
8
|
+
list_filter = ("contacted", "registered")
|
|
9
|
+
search_fields = ("email", "first_name", "last_name")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
admin.site.register(BetaSignup, BetaSignupAdmin)
|
beta/apps.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from django.apps import AppConfig
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BetaConfig(AppConfig):
|
|
5
|
+
name = "beta"
|
|
6
|
+
verbose_name = "Beta"
|
|
7
|
+
default_auto_field = "django.db.models.AutoField"
|
|
8
|
+
|
|
9
|
+
def ready(self):
|
|
10
|
+
# Importing the module connects the post_save signal handler.
|
|
11
|
+
from beta import listeners # noqa: F401
|
beta/forms.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from django import forms
|
|
2
|
+
from django.conf import settings
|
|
3
|
+
|
|
4
|
+
from beta.models import BetaSignup
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BetaSignupForm(forms.ModelForm):
|
|
8
|
+
def __init__(self, *args, **kwargs):
|
|
9
|
+
super().__init__(*args, **kwargs)
|
|
10
|
+
self.capture_first = getattr(settings, "BETA_CAPTURE_FIRST", False)
|
|
11
|
+
self.capture_both = getattr(settings, "BETA_CAPTURE_BOTH", False)
|
|
12
|
+
|
|
13
|
+
if self.capture_first:
|
|
14
|
+
self.fields.pop("last_name")
|
|
15
|
+
self.fields["first_name"].required = True
|
|
16
|
+
|
|
17
|
+
elif not self.capture_both:
|
|
18
|
+
self.fields.pop("first_name")
|
|
19
|
+
self.fields.pop("last_name")
|
|
20
|
+
else:
|
|
21
|
+
self.fields["first_name"].required = True
|
|
22
|
+
self.fields["last_name"].required = True
|
|
23
|
+
|
|
24
|
+
class Meta:
|
|
25
|
+
model = BetaSignup
|
|
26
|
+
exclude = ("contacted", "registered", "created")
|
beta/listeners.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from django.contrib.auth.models import User
|
|
2
|
+
from django.db.models.signals import post_save
|
|
3
|
+
|
|
4
|
+
from beta.models import BetaSignup
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def user_post_save_callback(sender, instance, created, **kwargs):
|
|
8
|
+
"""Mark a user as registered if a real User object is created"""
|
|
9
|
+
if created:
|
|
10
|
+
matches = BetaSignup.objects.filter(email=instance.email)
|
|
11
|
+
|
|
12
|
+
if matches:
|
|
13
|
+
matches[0].registered = True
|
|
14
|
+
matches[0].save()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
post_save.connect(user_post_save_callback, sender=User)
|
beta/managers.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BetaManager(models.Manager):
|
|
5
|
+
def contacted(self):
|
|
6
|
+
return self.get_queryset().filter(contacted=True)
|
|
7
|
+
|
|
8
|
+
def not_contacted(self):
|
|
9
|
+
return self.get_queryset().filter(contacted=False)
|
|
10
|
+
|
|
11
|
+
def registered(self):
|
|
12
|
+
return self.get_queryset().filter(registered=True)
|
|
13
|
+
|
|
14
|
+
def not_registered(self):
|
|
15
|
+
return self.get_queryset().filter(registered=False)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Generated by Django 5.2.16 on 2026-07-30 20:52
|
|
2
|
+
|
|
3
|
+
import django.utils.timezone
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
initial = True
|
|
9
|
+
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.CreateModel(
|
|
14
|
+
name="BetaSignup",
|
|
15
|
+
fields=[
|
|
16
|
+
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
|
17
|
+
("first_name", models.CharField(blank=True, max_length=50, verbose_name="First Name")),
|
|
18
|
+
("last_name", models.CharField(blank=True, max_length=75, verbose_name="Last Name")),
|
|
19
|
+
("email", models.EmailField(max_length=254, unique=True, verbose_name="Email Address")),
|
|
20
|
+
("contacted", models.BooleanField(default=False, verbose_name="Contacted")),
|
|
21
|
+
("registered", models.BooleanField(default=False, verbose_name="Registered")),
|
|
22
|
+
("created", models.DateTimeField(default=django.utils.timezone.now, verbose_name="Created")),
|
|
23
|
+
],
|
|
24
|
+
options={
|
|
25
|
+
"verbose_name": "Beta Signup",
|
|
26
|
+
"verbose_name_plural": "Beta Signups",
|
|
27
|
+
},
|
|
28
|
+
),
|
|
29
|
+
]
|
|
File without changes
|
beta/models.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from django.utils import timezone
|
|
3
|
+
from django.utils.translation import gettext_lazy as _
|
|
4
|
+
|
|
5
|
+
from beta.managers import BetaManager
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BetaSignup(models.Model):
|
|
9
|
+
"""
|
|
10
|
+
Model to store our pre-beta signups
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
first_name = models.CharField(_("First Name"), max_length=50, blank=True)
|
|
14
|
+
last_name = models.CharField(_("Last Name"), max_length=75, blank=True)
|
|
15
|
+
email = models.EmailField(_("Email Address"), unique=True)
|
|
16
|
+
|
|
17
|
+
contacted = models.BooleanField(_("Contacted"), default=False)
|
|
18
|
+
registered = models.BooleanField(_("Registered"), default=False)
|
|
19
|
+
|
|
20
|
+
created = models.DateTimeField(_("Created"), default=timezone.now)
|
|
21
|
+
|
|
22
|
+
objects = BetaManager()
|
|
23
|
+
|
|
24
|
+
class Meta:
|
|
25
|
+
verbose_name = _("Beta Signup")
|
|
26
|
+
verbose_name_plural = _("Beta Signups")
|
|
27
|
+
|
|
28
|
+
def __str__(self):
|
|
29
|
+
return f"Beta Signup - {self.email}"
|
beta/urls.py
ADDED
beta/views.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from django.urls import reverse
|
|
2
|
+
from django.views import generic
|
|
3
|
+
|
|
4
|
+
from beta.forms import BetaSignupForm
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Signup(generic.CreateView):
|
|
8
|
+
"""View to handle beta signup"""
|
|
9
|
+
|
|
10
|
+
template_name = "beta/signup.html"
|
|
11
|
+
form_class = BetaSignupForm
|
|
12
|
+
|
|
13
|
+
def get_success_url(self):
|
|
14
|
+
return reverse("beta_confirmation")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Confirmation(generic.TemplateView):
|
|
18
|
+
"""Confirmation Page"""
|
|
19
|
+
|
|
20
|
+
template_name = "beta/confirmation.html"
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-beta
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: django-beta is a reusable Django application for handling pre-beta signups.
|
|
5
|
+
Project-URL: Homepage, https://github.com/revsys/django-beta/
|
|
6
|
+
Author-email: Frank Wiles <frank@revsys.com>, Jeff Triplett <jeff@revsys.com>
|
|
7
|
+
License-File: AUTHORS.txt
|
|
8
|
+
License-File: LICENSE.txt
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Web Environment
|
|
11
|
+
Classifier: Framework :: Django
|
|
12
|
+
Classifier: Framework :: Django :: 4.2
|
|
13
|
+
Classifier: Framework :: Django :: 5.0
|
|
14
|
+
Classifier: Framework :: Django :: 5.1
|
|
15
|
+
Classifier: Framework :: Django :: 5.2
|
|
16
|
+
Classifier: Framework :: Django :: 6.0
|
|
17
|
+
Classifier: Framework :: Django :: 6.1
|
|
18
|
+
Classifier: Intended Audience :: Developers
|
|
19
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
27
|
+
Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Provides-Extra: lint
|
|
30
|
+
Requires-Dist: prek; extra == 'lint'
|
|
31
|
+
Provides-Extra: test
|
|
32
|
+
Requires-Dist: pytest; extra == 'test'
|
|
33
|
+
Requires-Dist: pytest-cov; extra == 'test'
|
|
34
|
+
Requires-Dist: pytest-django; extra == 'test'
|
|
35
|
+
Provides-Extra: testing
|
|
36
|
+
Requires-Dist: pytest; extra == 'testing'
|
|
37
|
+
Requires-Dist: pytest-cov; extra == 'testing'
|
|
38
|
+
Requires-Dist: pytest-django; extra == 'testing'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# django-beta
|
|
42
|
+
|
|
43
|
+
`django-beta` is a simple application to help you capture pre-beta interest
|
|
44
|
+
with your sites.
|
|
45
|
+
|
|
46
|
+
By default `django-beta` only captures a user's email address, however you
|
|
47
|
+
can alternately set one of these two configuration options:
|
|
48
|
+
|
|
49
|
+
- `BETA_CAPTURE_FIRST = True` will use a form and require the user to enter
|
|
50
|
+
their first name and email address.
|
|
51
|
+
- `BETA_CAPTURE_BOTH = True` will use a form and require the user to enter
|
|
52
|
+
their first name, last name, and email address.
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
Add `beta` to your `INSTALLED_APPS` and run migrations.
|
|
57
|
+
|
|
58
|
+
Add the following to your `urls.py`:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from django.urls import include, path
|
|
62
|
+
|
|
63
|
+
urlpatterns = [
|
|
64
|
+
path("beta/", include("beta.urls")),
|
|
65
|
+
]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Using the example templates provided in the code, create your customized beta
|
|
69
|
+
signup templates.
|
|
70
|
+
|
|
71
|
+
## Managers
|
|
72
|
+
|
|
73
|
+
The `BetaSignup` model has the following manager methods to help out:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
BetaSignup.objects.contacted()
|
|
77
|
+
BetaSignup.objects.not_contacted()
|
|
78
|
+
BetaSignup.objects.registered()
|
|
79
|
+
BetaSignup.objects.not_registered()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Side Effects
|
|
83
|
+
|
|
84
|
+
`django-beta` listens for a signal on User creation and marks the
|
|
85
|
+
corresponding `BetaSignup` entry as `registered`.
|
|
86
|
+
|
|
87
|
+
## Development
|
|
88
|
+
|
|
89
|
+
This project uses [nox](https://nox.thea.codes/) and
|
|
90
|
+
[just](https://github.com/casey/just) for testing and linting across a matrix
|
|
91
|
+
of Python and Django versions.
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
just lint # run pre-commit / ruff via prek
|
|
95
|
+
just test # run the full nox test matrix
|
|
96
|
+
just test-latest # run against the latest Python and Django
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## TODO
|
|
100
|
+
|
|
101
|
+
- Admin views to show beta registrations over time
|
|
102
|
+
- Management commands to simplify emailing the interested users
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
beta/__init__.py,sha256=mlI_y0X-IT2W5YNCpifdqxRIOLiENCSyne4ULTKm044,20
|
|
2
|
+
beta/admin.py,sha256=UACQoG2px9hr4GOBTZtIAAFKwod5FjjAGMMYQJYivwU,289
|
|
3
|
+
beta/apps.py,sha256=5ZZgvc32EVGin566btu3xv77BuT8bUOhezfXCjNNTN8,304
|
|
4
|
+
beta/forms.py,sha256=KhOZadiaOkTGQARV4OcHWv_K3PzNUvYGC7oVdxt5z9c,837
|
|
5
|
+
beta/listeners.py,sha256=y6mpyi0BBSWtxD3nInIgmcaO6_VmTef9sN1_hmEajpI,496
|
|
6
|
+
beta/managers.py,sha256=U61jWX8b90dZfVczw18T73EmwqsiruBUqli0dgzJhs0,415
|
|
7
|
+
beta/models.py,sha256=20YOFnAdughi-CL1elZnV0ZM-cUH5qQsyBKh2jcnw8g,877
|
|
8
|
+
beta/urls.py,sha256=l4LgdGsXN0Kfb87iYB6UnSmFS7Cmghl6U3_hz_Xm5wI,233
|
|
9
|
+
beta/views.py,sha256=3wDd1Z48mQAo6A0I1Bs-FLS2tqNGwy6qkqkLOPQ1Iqc,443
|
|
10
|
+
beta/migrations/0001_initial.py,sha256=HrN-wVMsTY7WRhvbfspDeFa-w_HUmwKtvA0Tf1zYfEQ,1202
|
|
11
|
+
beta/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
beta/templates/beta/confirmation.html,sha256=SSjcZeIdZSspnu4PRD1yuR6VZRvkdR89AVeqdwoqGPA,65
|
|
13
|
+
beta/templates/beta/signup.html,sha256=7N1BI2MNR9NHbIBqEs4XT0GfmxJ3dKuswEkz2gVuAnU,106
|
|
14
|
+
django_beta-0.2.0.dist-info/METADATA,sha256=3m7vBoURLHfL9UfOW-WbhPkYc34sLUu8iK4jEPpiHLM,3292
|
|
15
|
+
django_beta-0.2.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
16
|
+
django_beta-0.2.0.dist-info/licenses/AUTHORS.txt,sha256=-r87Jb1s2eRnqrW2gwWky-l0MC1fD594VdJmnKfJtiI,69
|
|
17
|
+
django_beta-0.2.0.dist-info/licenses/LICENSE.txt,sha256=b8ociThOjvtXY17Pt31eVPz7zGdtT3Pv1FWnunVY3Hk,1554
|
|
18
|
+
django_beta-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
django-beta was originally created by Frank Wiles <frank@revsys.com>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Copyright (c) Revolution Systems, LLC and individual contributors.
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
5
|
+
are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
|
12
|
+
documentation and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
3. Neither the name of django-beta nor the names of its contributors
|
|
15
|
+
may be used to endorse or promote products derived from this software
|
|
16
|
+
without specific prior written permission.
|
|
17
|
+
|
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
19
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
20
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
22
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
23
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
24
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
25
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
26
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|