Spaces:
Runtime error
Runtime error
Beracles commited on
Commit ·
7a5d455
1
Parent(s): fa0e770
register and models
Browse files- requirements.txt +2 -0
- src/main/db.sqlite3 +0 -0
- src/main/main/settings.py +6 -1
- src/main/templates/register.html +8 -0
- src/main/user/admin.py +8 -0
- src/main/user/forms.py +212 -0
- src/main/user/migrations/0001_initial.py +45 -0
- src/main/user/models.py +159 -0
- src/main/user/urls.py +1 -0
- src/main/user/utils.py +11 -0
- src/main/user/views.py +14 -1
requirements.txt
CHANGED
|
@@ -1,2 +1,4 @@
|
|
| 1 |
django
|
| 2 |
requests
|
|
|
|
|
|
|
|
|
| 1 |
django
|
| 2 |
requests
|
| 3 |
+
django-crispy-forms
|
| 4 |
+
crispy-bootstrap5
|
src/main/db.sqlite3
CHANGED
|
Binary files a/src/main/db.sqlite3 and b/src/main/db.sqlite3 differ
|
|
|
src/main/main/settings.py
CHANGED
|
@@ -37,7 +37,8 @@ INSTALLED_APPS = [
|
|
| 37 |
'django.contrib.sessions',
|
| 38 |
'django.contrib.messages',
|
| 39 |
'django.contrib.staticfiles',
|
| 40 |
-
|
|
|
|
| 41 |
'helloworld',
|
| 42 |
'user',
|
| 43 |
]
|
|
@@ -134,3 +135,7 @@ STATICFILES_DIRS = [
|
|
| 134 |
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
| 135 |
|
| 136 |
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
'django.contrib.sessions',
|
| 38 |
'django.contrib.messages',
|
| 39 |
'django.contrib.staticfiles',
|
| 40 |
+
"crispy_forms",
|
| 41 |
+
"crispy_bootstrap5",
|
| 42 |
'helloworld',
|
| 43 |
'user',
|
| 44 |
]
|
|
|
|
| 135 |
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
| 136 |
|
| 137 |
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
| 138 |
+
|
| 139 |
+
CRISPY_TEMPLATE_PACK = 'bootstrap5'
|
| 140 |
+
|
| 141 |
+
AUTH_USER_MODEL = 'user.CustomUser'
|
src/main/templates/register.html
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{% block title %} Create an Account {% endblock %}
|
| 2 |
+
{% block content %}
|
| 3 |
+
<form method="post" class="form-group">
|
| 4 |
+
{% csrf_token %}
|
| 5 |
+
{{ form }}
|
| 6 |
+
<button type="submit" class="btn btn-success">Register</button>
|
| 7 |
+
</form>
|
| 8 |
+
{% endblock %}
|
src/main/user/admin.py
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
|
|
|
|
|
| 1 |
from django.contrib import admin
|
| 2 |
|
| 3 |
# Register your models here.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from user.models import CustomUser
|
| 2 |
+
from django.contrib.auth.models import Group
|
| 3 |
from django.contrib import admin
|
| 4 |
|
| 5 |
# Register your models here.
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
admin.site.register(CustomUser)
|
| 11 |
+
admin.site.unregister(Group)
|
src/main/user/forms.py
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django import forms
|
| 2 |
+
from django.contrib.auth import authenticate, password_validation
|
| 3 |
+
from django.contrib.auth.forms import UsernameField, ReadOnlyPasswordHashField, UserModel
|
| 4 |
+
from django.core.exceptions import ValidationError
|
| 5 |
+
from django.utils.text import capfirst
|
| 6 |
+
from django.utils.translation import gettext_lazy as _
|
| 7 |
+
from .models import CustomUser
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class BaseCustomUserCreationForm(forms.ModelForm):
|
| 11 |
+
"""
|
| 12 |
+
A form that creates a user, with no privileges, from the given username and
|
| 13 |
+
password.
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
error_messages = {
|
| 17 |
+
"password_mismatch": _("The two password fields didn’t match."),
|
| 18 |
+
}
|
| 19 |
+
password1 = forms.CharField(
|
| 20 |
+
label=_("Password"),
|
| 21 |
+
strip=False,
|
| 22 |
+
widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
|
| 23 |
+
help_text=password_validation.password_validators_help_text_html(),
|
| 24 |
+
)
|
| 25 |
+
password2 = forms.CharField(
|
| 26 |
+
label=_("Password confirmation"),
|
| 27 |
+
widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
|
| 28 |
+
strip=False,
|
| 29 |
+
help_text=_("Enter the same password as before, for verification."),
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
class Meta:
|
| 33 |
+
model = CustomUser
|
| 34 |
+
fields = ("email", "username")
|
| 35 |
+
field_classes = {"email": forms.EmailField}
|
| 36 |
+
|
| 37 |
+
def __init__(self, *args, **kwargs):
|
| 38 |
+
super().__init__(*args, **kwargs)
|
| 39 |
+
if self._meta.model.EMAIL_FIELD in self.fields:
|
| 40 |
+
self.fields[self._meta.model.EMAIL_FIELD].widget.attrs[
|
| 41 |
+
"autofocus"
|
| 42 |
+
] = True
|
| 43 |
+
|
| 44 |
+
def clean_password2(self):
|
| 45 |
+
password1 = self.cleaned_data.get("password1")
|
| 46 |
+
password2 = self.cleaned_data.get("password2")
|
| 47 |
+
if password1 and password2 and password1 != password2:
|
| 48 |
+
raise ValidationError(
|
| 49 |
+
self.error_messages["password_mismatch"],
|
| 50 |
+
code="password_mismatch",
|
| 51 |
+
)
|
| 52 |
+
return password2
|
| 53 |
+
|
| 54 |
+
def _post_clean(self):
|
| 55 |
+
super()._post_clean()
|
| 56 |
+
# Validate the password after self.instance is updated with form data
|
| 57 |
+
# by super().
|
| 58 |
+
password = self.cleaned_data.get("password2")
|
| 59 |
+
if password:
|
| 60 |
+
try:
|
| 61 |
+
password_validation.validate_password(password, self.instance)
|
| 62 |
+
except ValidationError as error:
|
| 63 |
+
self.add_error("password2", error)
|
| 64 |
+
|
| 65 |
+
def save(self, commit=True):
|
| 66 |
+
user = super().save(commit=False)
|
| 67 |
+
user.set_password(self.cleaned_data["password1"])
|
| 68 |
+
if commit:
|
| 69 |
+
user.save()
|
| 70 |
+
if hasattr(self, "save_m2m"):
|
| 71 |
+
self.save_m2m()
|
| 72 |
+
return user
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
class CustomUserCreationForm(BaseCustomUserCreationForm):
|
| 76 |
+
def clean_username(self):
|
| 77 |
+
"""Reject emails that differ only in case."""
|
| 78 |
+
email = self.cleaned_data.get("email")
|
| 79 |
+
if (
|
| 80 |
+
email
|
| 81 |
+
and self._meta.model.objects.filter(username__iexact=email).exists()
|
| 82 |
+
):
|
| 83 |
+
self._update_errors(
|
| 84 |
+
ValidationError(
|
| 85 |
+
{
|
| 86 |
+
"email": self.instance.unique_error_message(
|
| 87 |
+
self._meta.model, ["email"]
|
| 88 |
+
)
|
| 89 |
+
}
|
| 90 |
+
)
|
| 91 |
+
)
|
| 92 |
+
else:
|
| 93 |
+
return email
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class CustomUserChangeForm(forms.ModelForm):
|
| 97 |
+
password = ReadOnlyPasswordHashField(
|
| 98 |
+
label=_("Password"),
|
| 99 |
+
help_text=_(
|
| 100 |
+
"Raw passwords are not stored, so there is no way to see this "
|
| 101 |
+
"user’s password, but you can change the password using "
|
| 102 |
+
'<a href="{}">this form</a>.'
|
| 103 |
+
),
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
class Meta:
|
| 107 |
+
model = CustomUser
|
| 108 |
+
fields = "__all__"
|
| 109 |
+
field_classes = {"email": UsernameField}
|
| 110 |
+
|
| 111 |
+
def __init__(self, *args, **kwargs):
|
| 112 |
+
super().__init__(*args, **kwargs)
|
| 113 |
+
password = self.fields.get("password")
|
| 114 |
+
if password:
|
| 115 |
+
password.help_text = password.help_text.format(
|
| 116 |
+
f"../../{self.instance.pk}/password/"
|
| 117 |
+
)
|
| 118 |
+
user_permissions = self.fields.get("user_permissions")
|
| 119 |
+
if user_permissions:
|
| 120 |
+
user_permissions.queryset = user_permissions.queryset.select_related(
|
| 121 |
+
"content_type"
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
class CustomAuthenticationForm(forms.Form):
|
| 126 |
+
"""
|
| 127 |
+
Base class for authenticating users. Extend this to get a form that accepts
|
| 128 |
+
username/password logins.
|
| 129 |
+
"""
|
| 130 |
+
|
| 131 |
+
username = UsernameField(widget=forms.TextInput(attrs={"autofocus": True}))
|
| 132 |
+
password = forms.CharField(
|
| 133 |
+
label=_("Password"),
|
| 134 |
+
strip=False,
|
| 135 |
+
widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
|
| 136 |
+
)
|
| 137 |
+
|
| 138 |
+
error_messages = {
|
| 139 |
+
"invalid_login": _(
|
| 140 |
+
"Please enter a correct %(username)s and password. Note that both "
|
| 141 |
+
"fields may be case-sensitive."
|
| 142 |
+
),
|
| 143 |
+
"inactive": _("This account is inactive."),
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
def __init__(self, request=None, *args, **kwargs):
|
| 147 |
+
"""
|
| 148 |
+
The 'request' parameter is set for custom auth use by subclasses.
|
| 149 |
+
The form data comes in via the standard 'data' kwarg.
|
| 150 |
+
"""
|
| 151 |
+
self.request = request
|
| 152 |
+
self.user_cache = None
|
| 153 |
+
super().__init__(*args, **kwargs)
|
| 154 |
+
|
| 155 |
+
# Set the max length and label for the "username" field.
|
| 156 |
+
self.email_field = UserModel._meta.get_field(UserModel.EMAIL_FIELD)
|
| 157 |
+
email_max_length = self.email_field.max_length or 254
|
| 158 |
+
self.fields["email"].max_length = email_max_length
|
| 159 |
+
self.fields["email"].widget.attrs["maxlength"] = email_max_length
|
| 160 |
+
if self.fields["email"].label is None:
|
| 161 |
+
self.fields["email"].label = capfirst(
|
| 162 |
+
self.email_field.verbose_name)
|
| 163 |
+
|
| 164 |
+
def clean(self):
|
| 165 |
+
email = self.cleaned_data.get("username")
|
| 166 |
+
password = self.cleaned_data.get("password")
|
| 167 |
+
|
| 168 |
+
if email is not None and password:
|
| 169 |
+
self.user_cache = authenticate(
|
| 170 |
+
self.request, email=email, password=password
|
| 171 |
+
)
|
| 172 |
+
if self.user_cache is None:
|
| 173 |
+
raise self.get_invalid_login_error()
|
| 174 |
+
else:
|
| 175 |
+
self.confirm_login_allowed(self.user_cache)
|
| 176 |
+
|
| 177 |
+
return self.cleaned_data
|
| 178 |
+
|
| 179 |
+
def confirm_login_allowed(self, user):
|
| 180 |
+
"""
|
| 181 |
+
Controls whether the given User may log in. This is a policy setting,
|
| 182 |
+
independent of end-user authentication. This default behavior is to
|
| 183 |
+
allow login by active users, and reject login by inactive users.
|
| 184 |
+
|
| 185 |
+
If the given user cannot log in, this method should raise a
|
| 186 |
+
``ValidationError``.
|
| 187 |
+
|
| 188 |
+
If the given user may log in, this method should return None.
|
| 189 |
+
"""
|
| 190 |
+
if not user.is_active:
|
| 191 |
+
raise ValidationError(
|
| 192 |
+
self.error_messages["inactive"],
|
| 193 |
+
code="inactive",
|
| 194 |
+
)
|
| 195 |
+
|
| 196 |
+
def get_user(self):
|
| 197 |
+
return self.user_cache
|
| 198 |
+
|
| 199 |
+
def get_invalid_login_error(self):
|
| 200 |
+
return ValidationError(
|
| 201 |
+
self.error_messages["invalid_login"],
|
| 202 |
+
code="invalid_login",
|
| 203 |
+
params={"email": self.email_field.verbose_name},
|
| 204 |
+
)
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
class RegisterForm(CustomUserCreationForm):
|
| 208 |
+
email = forms.EmailField()
|
| 209 |
+
|
| 210 |
+
class Meta:
|
| 211 |
+
model = CustomUser
|
| 212 |
+
fields = ['email', 'username', 'password1', 'password2']
|
src/main/user/migrations/0001_initial.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Generated by Django 5.0.3 on 2024-03-25 13:35
|
| 2 |
+
|
| 3 |
+
import django.core.validators
|
| 4 |
+
import django.utils.timezone
|
| 5 |
+
import user.models
|
| 6 |
+
from django.db import migrations, models
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class Migration(migrations.Migration):
|
| 10 |
+
|
| 11 |
+
initial = True
|
| 12 |
+
|
| 13 |
+
dependencies = [
|
| 14 |
+
('auth', '0012_alter_user_first_name_max_length'),
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
operations = [
|
| 18 |
+
migrations.CreateModel(
|
| 19 |
+
name='CustomUser',
|
| 20 |
+
fields=[
|
| 21 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
| 22 |
+
('password', models.CharField(max_length=128, verbose_name='password')),
|
| 23 |
+
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
| 24 |
+
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
| 25 |
+
('email', models.EmailField(error_messages={'unique': 'A user with that email already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.core.validators.EmailValidator()], verbose_name='email')),
|
| 26 |
+
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
|
| 27 |
+
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
|
| 28 |
+
('username', models.CharField(blank=True, max_length=150, verbose_name='username')),
|
| 29 |
+
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
| 30 |
+
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
| 31 |
+
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
| 32 |
+
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
|
| 33 |
+
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
| 34 |
+
],
|
| 35 |
+
options={
|
| 36 |
+
'verbose_name': 'user',
|
| 37 |
+
'verbose_name_plural': 'users',
|
| 38 |
+
'abstract': False,
|
| 39 |
+
'swappable': 'AUTH_USER_MODEL',
|
| 40 |
+
},
|
| 41 |
+
managers=[
|
| 42 |
+
('objects', user.models.CustomUserManager()),
|
| 43 |
+
],
|
| 44 |
+
),
|
| 45 |
+
]
|
src/main/user/models.py
CHANGED
|
@@ -1,3 +1,162 @@
|
|
| 1 |
from django.db import models
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
# Create your models here.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from django.db import models
|
| 2 |
+
from django.contrib.auth.models import (
|
| 3 |
+
AbstractBaseUser, PermissionsMixin, BaseUserManager)
|
| 4 |
+
from django.core.validators import EmailValidator
|
| 5 |
+
from django.core.mail import send_mail
|
| 6 |
+
from django.utils import timezone
|
| 7 |
+
from django.utils.translation import gettext_lazy as _
|
| 8 |
+
from django.apps import apps
|
| 9 |
+
from django.contrib.auth.hashers import make_password
|
| 10 |
+
from django.contrib import auth
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class CustomUserManager(BaseUserManager):
|
| 14 |
+
use_in_migrations = True
|
| 15 |
+
|
| 16 |
+
def _create_user(self, username, email, password, **extra_fields):
|
| 17 |
+
"""
|
| 18 |
+
Create and save a user with the given username, email, and password.
|
| 19 |
+
"""
|
| 20 |
+
if not email:
|
| 21 |
+
raise ValueError("The given email must be set")
|
| 22 |
+
email = self.normalize_email(email)
|
| 23 |
+
# Lookup the real model class from the global app registry so this
|
| 24 |
+
# manager method can be used in migrations. This is fine because
|
| 25 |
+
# managers are by definition working on the real model.
|
| 26 |
+
GlobalUserModel = apps.get_model(
|
| 27 |
+
self.model._meta.app_label, self.model._meta.object_name
|
| 28 |
+
)
|
| 29 |
+
username = GlobalUserModel.normalize_username(username)
|
| 30 |
+
user = self.model(username=username, email=email, **extra_fields)
|
| 31 |
+
user.password = make_password(password)
|
| 32 |
+
user.save(using=self._db)
|
| 33 |
+
return user
|
| 34 |
+
|
| 35 |
+
def create_user(self, email, username=None, password=None, **extra_fields):
|
| 36 |
+
extra_fields.setdefault("is_staff", False)
|
| 37 |
+
extra_fields.setdefault("is_superuser", False)
|
| 38 |
+
return self._create_user(username, email, password, **extra_fields)
|
| 39 |
+
|
| 40 |
+
def create_superuser(self, username, email=None, password=None, **extra_fields):
|
| 41 |
+
extra_fields.setdefault("is_staff", True)
|
| 42 |
+
extra_fields.setdefault("is_superuser", True)
|
| 43 |
+
|
| 44 |
+
if extra_fields.get("is_staff") is not True:
|
| 45 |
+
raise ValueError("Superuser must have is_staff=True.")
|
| 46 |
+
if extra_fields.get("is_superuser") is not True:
|
| 47 |
+
raise ValueError("Superuser must have is_superuser=True.")
|
| 48 |
+
|
| 49 |
+
return self._create_user(username, email, password, **extra_fields)
|
| 50 |
+
|
| 51 |
+
def with_perm(
|
| 52 |
+
self, perm, is_active=True, include_superusers=True, backend=None, obj=None
|
| 53 |
+
):
|
| 54 |
+
if backend is None:
|
| 55 |
+
backends = auth._get_backends(return_tuples=True)
|
| 56 |
+
if len(backends) == 1:
|
| 57 |
+
backend, _ = backends[0]
|
| 58 |
+
else:
|
| 59 |
+
raise ValueError(
|
| 60 |
+
"You have multiple authentication backends configured and "
|
| 61 |
+
"therefore must provide the `backend` argument."
|
| 62 |
+
)
|
| 63 |
+
elif not isinstance(backend, str):
|
| 64 |
+
raise TypeError(
|
| 65 |
+
"backend must be a dotted import path string (got %r)." % backend
|
| 66 |
+
)
|
| 67 |
+
else:
|
| 68 |
+
backend = auth.load_backend(backend)
|
| 69 |
+
if hasattr(backend, "with_perm"):
|
| 70 |
+
return backend.with_perm(
|
| 71 |
+
perm,
|
| 72 |
+
is_active=is_active,
|
| 73 |
+
include_superusers=include_superusers,
|
| 74 |
+
obj=obj,
|
| 75 |
+
)
|
| 76 |
+
return self.none()
|
| 77 |
|
| 78 |
# Create your models here.
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
class AbstractCustomUser(AbstractBaseUser, PermissionsMixin):
|
| 82 |
+
"""
|
| 83 |
+
An abstract base class implementing a fully featured User model with
|
| 84 |
+
admin-compliant permissions.
|
| 85 |
+
|
| 86 |
+
Email and password are required. Other fields are optional.
|
| 87 |
+
"""
|
| 88 |
+
|
| 89 |
+
email_validator = EmailValidator()
|
| 90 |
+
|
| 91 |
+
email = models.EmailField(
|
| 92 |
+
_("email"),
|
| 93 |
+
max_length=150,
|
| 94 |
+
unique=True,
|
| 95 |
+
help_text=_(
|
| 96 |
+
"Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
|
| 97 |
+
),
|
| 98 |
+
validators=[email_validator],
|
| 99 |
+
error_messages={
|
| 100 |
+
"unique": _("A user with that email already exists."),
|
| 101 |
+
},
|
| 102 |
+
)
|
| 103 |
+
first_name = models.CharField(_("first name"), max_length=150, blank=True)
|
| 104 |
+
last_name = models.CharField(_("last name"), max_length=150, blank=True)
|
| 105 |
+
username = models.CharField(_("username"), max_length=150, blank=True)
|
| 106 |
+
is_staff = models.BooleanField(
|
| 107 |
+
_("staff status"),
|
| 108 |
+
default=False,
|
| 109 |
+
help_text=_(
|
| 110 |
+
"Designates whether the user can log into this admin site."),
|
| 111 |
+
)
|
| 112 |
+
is_active = models.BooleanField(
|
| 113 |
+
_("active"),
|
| 114 |
+
default=True,
|
| 115 |
+
help_text=_(
|
| 116 |
+
"Designates whether this user should be treated as active. "
|
| 117 |
+
"Unselect this instead of deleting accounts."
|
| 118 |
+
),
|
| 119 |
+
)
|
| 120 |
+
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
|
| 121 |
+
|
| 122 |
+
objects = CustomUserManager()
|
| 123 |
+
|
| 124 |
+
EMAIL_FIELD = "username"
|
| 125 |
+
USERNAME_FIELD = "email"
|
| 126 |
+
REQUIRED_FIELDS = ["username"]
|
| 127 |
+
|
| 128 |
+
class Meta:
|
| 129 |
+
verbose_name = _("user")
|
| 130 |
+
verbose_name_plural = _("users")
|
| 131 |
+
abstract = True
|
| 132 |
+
|
| 133 |
+
def clean(self):
|
| 134 |
+
super().clean()
|
| 135 |
+
self.email = self.__class__.objects.normalize_email(self.email)
|
| 136 |
+
|
| 137 |
+
def get_full_name(self):
|
| 138 |
+
"""
|
| 139 |
+
Return the first_name plus the last_name, with a space in between.
|
| 140 |
+
"""
|
| 141 |
+
full_name = "%s %s" % (self.first_name, self.last_name)
|
| 142 |
+
return full_name.strip()
|
| 143 |
+
|
| 144 |
+
def get_short_name(self):
|
| 145 |
+
"""Return the short name for the user."""
|
| 146 |
+
return self.first_name
|
| 147 |
+
|
| 148 |
+
def email_user(self, subject, message, from_email=None, **kwargs):
|
| 149 |
+
"""Send an email to this user."""
|
| 150 |
+
send_mail(subject, message, from_email, [self.email], **kwargs)
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
class CustomUser(AbstractCustomUser):
|
| 154 |
+
"""
|
| 155 |
+
Users within the Django authentication system are represented by this
|
| 156 |
+
model.
|
| 157 |
+
|
| 158 |
+
Email and password are required. Other fields are optional.
|
| 159 |
+
"""
|
| 160 |
+
|
| 161 |
+
class Meta(AbstractCustomUser.Meta):
|
| 162 |
+
swappable = "AUTH_USER_MODEL"
|
src/main/user/urls.py
CHANGED
|
@@ -21,4 +21,5 @@ app_name = 'user'
|
|
| 21 |
urlpatterns = [
|
| 22 |
path('login/', views.login, name="login"),
|
| 23 |
path('verify_password/', views.verify_password),
|
|
|
|
| 24 |
]
|
|
|
|
| 21 |
urlpatterns = [
|
| 22 |
path('login/', views.login, name="login"),
|
| 23 |
path('verify_password/', views.verify_password),
|
| 24 |
+
path('register/', views.register, name="register"),
|
| 25 |
]
|
src/main/user/utils.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .models import CustomUser
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def export_user_to_json():
|
| 5 |
+
# q=CustomUser.objects.create(key="value") # 插入数据
|
| 6 |
+
q = list(q)
|
| 7 |
+
for i in q:
|
| 8 |
+
print(i.email)
|
| 9 |
+
print(i.password)
|
| 10 |
+
print(i.username)
|
| 11 |
+
# todo: 写入json文件
|
src/main/user/views.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
import os
|
| 2 |
from django.http import HttpResponse, HttpResponseRedirect
|
| 3 |
from django.shortcuts import render, redirect
|
|
|
|
| 4 |
import requests
|
| 5 |
from . import status
|
| 6 |
-
|
| 7 |
# Create your views here.
|
| 8 |
|
| 9 |
base_url = "https://pgsoft-pguser.hf.space"
|
|
@@ -68,3 +68,16 @@ def verify_password(request) -> HttpResponse | HttpResponseRedirect:
|
|
| 68 |
"email": email,
|
| 69 |
}
|
| 70 |
return render(request, "loggedin.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
from django.http import HttpResponse, HttpResponseRedirect
|
| 3 |
from django.shortcuts import render, redirect
|
| 4 |
+
from .forms import RegisterForm
|
| 5 |
import requests
|
| 6 |
from . import status
|
|
|
|
| 7 |
# Create your views here.
|
| 8 |
|
| 9 |
base_url = "https://pgsoft-pguser.hf.space"
|
|
|
|
| 68 |
"email": email,
|
| 69 |
}
|
| 70 |
return render(request, "loggedin.html", context)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def register(request):
|
| 74 |
+
if request.method == "POST":
|
| 75 |
+
print("posting")
|
| 76 |
+
form = RegisterForm(request.POST)
|
| 77 |
+
if form.is_valid():
|
| 78 |
+
form.save()
|
| 79 |
+
# upload to dataset
|
| 80 |
+
return redirect("/")
|
| 81 |
+
else:
|
| 82 |
+
form = RegisterForm()
|
| 83 |
+
return render(request, "register.html", {"form": form})
|