Database + User and Metric CRUD
This commit is contained in:
parent
144191b329
commit
276168f328
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
FROM python:3.9-slim
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt /app/
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
COPY . /app/
|
||||||
|
CMD ["python", "server/manage.py", "runserver", "0.0.0.0:8000"]
|
||||||
|
|
||||||
|
EXPOSE 8000
|
40
docker-compose.yaml
Normal file
40
docker-compose.yaml
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
version: '3.9'
|
||||||
|
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres:17.0
|
||||||
|
container_name: postgres-database
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: ${DATABASE_NAME}
|
||||||
|
POSTGRES_USER: ${DATABASE_USER}
|
||||||
|
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
networks:
|
||||||
|
backend:
|
||||||
|
aliases:
|
||||||
|
- "db"
|
||||||
|
|
||||||
|
back:
|
||||||
|
build:
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: persistence
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
volumes:
|
||||||
|
- .:/app
|
||||||
|
|
||||||
|
networks:
|
||||||
|
backend:
|
||||||
|
aliases:
|
||||||
|
- "back"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
backend:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
BIN
requirements.txt
Normal file
BIN
requirements.txt
Normal file
Binary file not shown.
0
server/exercise/__init__.py
Normal file
0
server/exercise/__init__.py
Normal file
3
server/exercise/admin.py
Normal file
3
server/exercise/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
server/exercise/apps.py
Normal file
6
server/exercise/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ExerciseConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'exercise'
|
0
server/exercise/migrations/__init__.py
Normal file
0
server/exercise/migrations/__init__.py
Normal file
3
server/exercise/models.py
Normal file
3
server/exercise/models.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
3
server/exercise/tests.py
Normal file
3
server/exercise/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
3
server/exercise/views.py
Normal file
3
server/exercise/views.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
0
server/gym_program/__init__.py
Normal file
0
server/gym_program/__init__.py
Normal file
3
server/gym_program/admin.py
Normal file
3
server/gym_program/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
server/gym_program/apps.py
Normal file
6
server/gym_program/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class GymProgramConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'gym_program'
|
0
server/gym_program/migrations/__init__.py
Normal file
0
server/gym_program/migrations/__init__.py
Normal file
3
server/gym_program/models.py
Normal file
3
server/gym_program/models.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
3
server/gym_program/tests.py
Normal file
3
server/gym_program/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
3
server/gym_program/views.py
Normal file
3
server/gym_program/views.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
0
server/metric/__init__.py
Normal file
0
server/metric/__init__.py
Normal file
3
server/metric/admin.py
Normal file
3
server/metric/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
server/metric/apps.py
Normal file
6
server/metric/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class MetricConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'metric'
|
29
server/metric/migrations/0001_initial.py
Normal file
29
server/metric/migrations/0001_initial.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Generated by Django 4.2.16 on 2024-10-05 14:16
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Metric',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('gender', models.CharField(choices=[('M', 'Male'), ('F', 'Female')], default='M', max_length=1)),
|
||||||
|
('weight', models.FloatField(default=0.0, validators=[django.core.validators.MinValueValidator(0.0)])),
|
||||||
|
('height', models.FloatField(default=0.0, validators=[django.core.validators.MinValueValidator(0.0)])),
|
||||||
|
('birth_date', models.DateField(default='2000-01-01')),
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
0
server/metric/migrations/__init__.py
Normal file
0
server/metric/migrations/__init__.py
Normal file
23
server/metric/models.py
Normal file
23
server/metric/models.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.core.validators import MinValueValidator
|
||||||
|
|
||||||
|
|
||||||
|
class Metric(models.Model):
|
||||||
|
class Gender(models.TextChoices):
|
||||||
|
MALE = 'M', _('Male')
|
||||||
|
FEMALE = 'F', _('Female')
|
||||||
|
|
||||||
|
user = models.OneToOneField('user.User', on_delete=models.CASCADE)
|
||||||
|
gender = models.CharField(
|
||||||
|
max_length=1,
|
||||||
|
choices=Gender.choices,
|
||||||
|
default=Gender.MALE,
|
||||||
|
blank=False,
|
||||||
|
)
|
||||||
|
weight = models.FloatField(blank=False, validators=[MinValueValidator(0.0)], default=0.0)
|
||||||
|
height = models.FloatField(blank=False, validators=[MinValueValidator(0.0)], default=0.0)
|
||||||
|
birth_date = models.DateField(blank=False, null=False, default='2000-01-01')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.gender}, Weight: {self.weight}, Height: {self.height}, Birth date: {self.birth_date}"
|
13
server/metric/serializers.py
Normal file
13
server/metric/serializers.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
from .models import Metric
|
||||||
|
|
||||||
|
|
||||||
|
class MetricSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Metric
|
||||||
|
fields = ('id',
|
||||||
|
'gender',
|
||||||
|
'weight',
|
||||||
|
'height',
|
||||||
|
'birth_date'
|
||||||
|
)
|
3
server/metric/tests.py
Normal file
3
server/metric/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
7
server/metric/urls.py
Normal file
7
server/metric/urls.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from django.urls import path
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('api/metrics/', views.metric_list),
|
||||||
|
path('api/metric/', views.metric_detail),
|
||||||
|
]
|
46
server/metric/views.py
Normal file
46
server/metric/views.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from rest_framework.decorators import api_view
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from .models import Metric
|
||||||
|
from .serializers import MetricSerializer
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['GET', 'POST'])
|
||||||
|
def metric_list(request):
|
||||||
|
if request.method == 'GET':
|
||||||
|
metrics = Metric.objects.all()
|
||||||
|
serializer = MetricSerializer(metrics, many=True)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['GET', 'PUT', 'POST', 'DELETE'])
|
||||||
|
def metric_detail(request):
|
||||||
|
user = request.user
|
||||||
|
|
||||||
|
if request.method == 'GET':
|
||||||
|
metric = get_object_or_404(Metric, user=user)
|
||||||
|
serializer = MetricSerializer(metric)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
elif request.method == 'PUT':
|
||||||
|
metric = get_object_or_404(Metric, user=user)
|
||||||
|
serializer = MetricSerializer(metric, data=request.data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response(serializer.data)
|
||||||
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
elif request.method == 'POST':
|
||||||
|
if Metric.objects.filter(user=user).exists():
|
||||||
|
return Response({'detail': 'Metric already exists for this user.'}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
serializer = MetricSerializer(data=request.data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save(user=user)
|
||||||
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||||
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
elif request.method == 'DELETE':
|
||||||
|
metric = get_object_or_404(Metric, user=user)
|
||||||
|
metric.delete()
|
||||||
|
return Response({'detail': 'Metric deleted successfully.'}, status=status.HTTP_204_NO_CONTENT)
|
@ -9,23 +9,26 @@ https://docs.djangoproject.com/en/4.2/topics/settings/
|
|||||||
For the full list of settings and their values, see
|
For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/4.2/ref/settings/
|
https://docs.djangoproject.com/en/4.2/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
from datetime import timedelta
|
||||||
|
import environ
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
env = environ.Env()
|
||||||
|
environ.Env.read_env(BASE_DIR / '../.env')
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = 'django-insecure-2edm6&uow19ulf2@+x%q@e+9!6$6u852^s%!o6k(1z^605h%v4'
|
SECRET_KEY = env('SECRET_KEY')
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = env.bool('DEBUG', default=False)
|
||||||
|
|
||||||
ALLOWED_HOSTS = []
|
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=[])
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
@ -37,6 +40,17 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'django.contrib.sites',
|
||||||
|
'rest_framework',
|
||||||
|
'rest_framework.authtoken',
|
||||||
|
'allauth',
|
||||||
|
'allauth.account',
|
||||||
|
'allauth.socialaccount',
|
||||||
|
'dj_rest_auth',
|
||||||
|
'dj_rest_auth.registration',
|
||||||
|
'corsheaders',
|
||||||
|
'user.apps.UserConfig',
|
||||||
|
'metric.apps.MetricConfig',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
@ -47,8 +61,15 @@ MIDDLEWARE = [
|
|||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
'corsheaders.middleware.CorsMiddleware',
|
||||||
|
'allauth.account.middleware.AccountMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
CORS_ORIGIN_ALLOW_ALL = False
|
||||||
|
CORS_ORIGIN_WHITELIST = (
|
||||||
|
'http://localhost:8080',
|
||||||
|
)
|
||||||
|
|
||||||
ROOT_URLCONF = 'server.urls'
|
ROOT_URLCONF = 'server.urls'
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
@ -75,8 +96,12 @@ WSGI_APPLICATION = 'server.wsgi.application'
|
|||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
'NAME': env('DATABASE_NAME'),
|
||||||
|
'USER': env('DATABASE_USER'),
|
||||||
|
'PASSWORD': env('DATABASE_PASSWORD'),
|
||||||
|
'HOST': env('DATABASE_HOST'),
|
||||||
|
'PORT': env('DATABASE_PORT'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +124,27 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
SITE_ID = 1
|
||||||
|
DJANGO_REST_AUTH_TOKEN_MODEL = None
|
||||||
|
|
||||||
|
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
|
||||||
|
ACCOUNT_AUTHENTICATION_METHOD = 'email'
|
||||||
|
ACCOUNT_EMAIL_REQUIRED = True
|
||||||
|
ACCOUNT_UNIQUE_EMAIL = True
|
||||||
|
ACCOUNT_USERNAME_REQUIRED = False
|
||||||
|
ACCOUNT_USER_EMAIL_FIELD = 'email'
|
||||||
|
ACCOUNT_LOGOUT_ON_GET = False
|
||||||
|
ACCOUNT_EMAIL_VERIFICATION = 'none'
|
||||||
|
|
||||||
|
AUTH_USER_MODEL = 'user.User'
|
||||||
|
|
||||||
|
REST_AUTH_SERIALIZERS = {
|
||||||
|
"USER_DETAILS_SERIALIZER": "user.serializers.CustomUserDetailsSerializer",
|
||||||
|
}
|
||||||
|
REST_AUTH_REGISTER_SERIALIZERS = {
|
||||||
|
"REGISTER_SERIALIZER": "user.serializers.CustomRegisterSerializer",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
|
@ -15,8 +15,11 @@ Including another URLconf
|
|||||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path
|
from django.urls import path, include
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
|
path('auth/', include('dj_rest_auth.urls')),
|
||||||
|
path('auth/registration/', include('dj_rest_auth.registration.urls')),
|
||||||
|
path('', include('metric.urls')),
|
||||||
]
|
]
|
||||||
|
0
server/training_day/__init__.py
Normal file
0
server/training_day/__init__.py
Normal file
3
server/training_day/admin.py
Normal file
3
server/training_day/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
server/training_day/apps.py
Normal file
6
server/training_day/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class TrainingDayConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'training_day'
|
0
server/training_day/migrations/__init__.py
Normal file
0
server/training_day/migrations/__init__.py
Normal file
3
server/training_day/models.py
Normal file
3
server/training_day/models.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
3
server/training_day/tests.py
Normal file
3
server/training_day/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
3
server/training_day/views.py
Normal file
3
server/training_day/views.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
0
server/user/__init__.py
Normal file
0
server/user/__init__.py
Normal file
3
server/user/admin.py
Normal file
3
server/user/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
server/user/apps.py
Normal file
6
server/user/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class UserConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'user'
|
36
server/user/migrations/0001_initial.py
Normal file
36
server/user/migrations/0001_initial.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Generated by Django 4.2.16 on 2024-10-05 11:19
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import user.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '0012_alter_user_first_name_max_length'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='User',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||||
|
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||||
|
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||||
|
('email', models.EmailField(max_length=254, unique=True)),
|
||||||
|
('is_active', models.BooleanField(default=True)),
|
||||||
|
('is_staff', models.BooleanField(default=False)),
|
||||||
|
('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')),
|
||||||
|
('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')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
('objects', user.models.UserManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
0
server/user/migrations/__init__.py
Normal file
0
server/user/migrations/__init__.py
Normal file
35
server/user/models.py
Normal file
35
server/user/models.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class UserManager(BaseUserManager):
|
||||||
|
use_in_migrations = True
|
||||||
|
|
||||||
|
def create_user(self, email, password=None, **extra_fields):
|
||||||
|
if not email:
|
||||||
|
raise ValueError("Email address must be provided")
|
||||||
|
email = self.normalize_email(email)
|
||||||
|
user = self.model(email=email, **extra_fields)
|
||||||
|
user.set_password(password)
|
||||||
|
user.save(using=self._db)
|
||||||
|
return user
|
||||||
|
|
||||||
|
def create_superuser(self, email, password=None, **extra_fields):
|
||||||
|
extra_fields.setdefault('is_staff', True)
|
||||||
|
extra_fields.setdefault('is_superuser', True)
|
||||||
|
|
||||||
|
return self.create_user(email, password, **extra_fields)
|
||||||
|
|
||||||
|
|
||||||
|
class User(AbstractBaseUser, PermissionsMixin):
|
||||||
|
email = models.EmailField(unique=True)
|
||||||
|
is_active = models.BooleanField(default=True)
|
||||||
|
is_staff = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
objects = UserManager()
|
||||||
|
|
||||||
|
USERNAME_FIELD = 'email'
|
||||||
|
REQUIRED_FIELDS = []
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.email
|
26
server/user/serializers.py
Normal file
26
server/user/serializers.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from dj_rest_auth.registration.serializers import RegisterSerializer
|
||||||
|
from rest_framework import serializers
|
||||||
|
from .models import User
|
||||||
|
|
||||||
|
|
||||||
|
class CustomRegisterSerializer(RegisterSerializer):
|
||||||
|
email = serializers.EmailField(required=True)
|
||||||
|
password1 = serializers.CharField(write_only=True)
|
||||||
|
password2 = serializers.CharField(write_only=True)
|
||||||
|
|
||||||
|
def get_cleaned_data(self):
|
||||||
|
super(CustomRegisterSerializer, self).get_cleaned_data()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'email': self.validated_data.get('email', ''),
|
||||||
|
'password1': self.validated_data.get('password1', ''),
|
||||||
|
'password2': self.validated_data.get('password2', ''),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CustomUserDetailsSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = ('email',)
|
||||||
|
read_only_fields = ('email',)
|
||||||
|
|
3
server/user/tests.py
Normal file
3
server/user/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
6
server/user/views.py
Normal file
6
server/user/views.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from dj_rest_auth.registration.views import RegisterView
|
||||||
|
from .models import User
|
||||||
|
|
||||||
|
|
||||||
|
class CustomRegisterView(RegisterView):
|
||||||
|
queryset = User.objects.all()
|
Loading…
Reference in New Issue
Block a user