profile end points user model otp stuff base

This commit is contained in:
Parsa Nazer
2024-12-13 23:02:19 +03:30
parent eef8263869
commit 259099cb9e
16 changed files with 425 additions and 7 deletions
+7 -1
View File
@@ -1,3 +1,9 @@
from django.contrib import admin
from .models import *
from unfold.admin import ModelAdmin
# Register your models here.
@admin.register(User)
class UserAdmin(ModelAdmin):
list_display = ['phone', 'email', 'is_superuser']
readonly_fields = ['password', 'last_login', 'otp_expiry']
@@ -0,0 +1,39 @@
# Generated by Django 5.1.2 on 2024-12-13 17:49
from django.db import migrations, 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=255, unique=True, verbose_name='ایمیل')),
('phone_number', models.CharField(max_length=12, unique=True, verbose_name='شماره تماس')),
('first_name', models.CharField(blank=True, max_length=50, verbose_name='نام')),
('last_name', models.CharField(blank=True, max_length=50, verbose_name='نام خانوادگی')),
('profile_photo', models.ImageField(blank=True, null=True, upload_to='profile_photos/', verbose_name='عکس پروفایل')),
('is_active', models.BooleanField(default=True)),
('is_staff', models.BooleanField(default=False)),
('date_joined', models.DateTimeField(auto_now_add=True, verbose_name='تاریخ ثبتنام')),
('otp', models.CharField(blank=True, max_length=6, null=True, verbose_name='تاریخ ثبتنام')),
('otp_expiry', models.DateTimeField(blank=True, null=True, verbose_name='تاریخ تمام شدن otp')),
('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,
},
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2024-12-13 17:51
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('account', '0001_initial'),
]
operations = [
migrations.RenameField(
model_name='user',
old_name='phone_number',
new_name='phone',
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2024-12-13 17:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0002_rename_phone_number_user_phone'),
]
operations = [
migrations.AlterField(
model_name='user',
name='email',
field=models.EmailField(max_length=255, verbose_name='ایمیل'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2024-12-13 19:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0003_alter_user_email'),
]
operations = [
migrations.AlterField(
model_name='user',
name='email',
field=models.EmailField(blank=True, max_length=255, null=True, verbose_name='ایمیل'),
),
]
@@ -0,0 +1,21 @@
# Generated by Django 5.1.2 on 2024-12-13 19:13
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('account', '0004_alter_user_email'),
]
operations = [
migrations.RemoveField(
model_name='user',
name='groups',
),
migrations.RemoveField(
model_name='user',
name='user_permissions',
),
]
+98 -1
View File
@@ -1,3 +1,100 @@
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
from django.utils.translation import gettext_lazy as _
import random
from datetime import datetime, timedelta
from django.utils import timezone
from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken, OutstandingToken
class UserManager(BaseUserManager):
def create_user(self, phone, password=None):
if not phone:
raise ValueError('Users must have a phone number')
user = self.model(
phone=phone,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, phone, password=None):
user = self.create_user(
phone=phone,
)
user.is_staff = True
user.is_superuser = True
user.set_password(password)
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, verbose_name='ایمیل', blank=True, null=True)
phone = models.CharField(max_length=12, verbose_name='شماره تماس', unique=True)
first_name = models.CharField(max_length=50, blank=True, verbose_name='نام')
last_name = models.CharField(max_length=50, blank=True, verbose_name='نام خانوادگی')
profile_photo = models.ImageField(upload_to='profile_photos/', null=True, blank=True, verbose_name='عکس پروفایل')
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True, verbose_name='تاریخ ثبتنام')
otp = models.CharField(max_length=6, blank=True, null=True, verbose_name='تاریخ ثبتنام')
otp_expiry = models.DateTimeField(blank=True, null=True, verbose_name='تاریخ تمام شدن otp')
objects = UserManager()
USERNAME_FIELD = 'phone'
REQUIRED_FIELDS = []
@property
def groups(self):
return None
@property
def user_permissions(self):
return None
def set_otp(self):
self.otp = str(random.randint(100000, 999999))
self.otp_expiry = timezone.now() + timedelta(minutes=5)
self.save()
def clear_otp(self):
self.otp = None
self.otp_expiry = None
self.save()
def verify_otp(self, otp_code):
if self.otp == otp_code and self.otp_expiry > timezone.now():
return True
return False
def blacklist_user_tokens(self):
try:
tokens = OutstandingToken.objects.filter(user=self)
for token in tokens:
BlacklistedToken.objects.get_or_create(token=token)
print('done')
except Exception as e:
print(f"ridi dadash")
def __str__(self):
if self.first_name and self.last_name:
return f'{self.first_name} {self.last_name}'
else:
return self.email
def get_name(self):
if self.first_name and self.last_name:
return f'{self.first_name} {self.last_name}'
else:
return self.email
# Create your models here.
+11
View File
@@ -0,0 +1,11 @@
from .models import *
from rest_framework import serializers
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email', 'profile_photo', 'phone']
read_only_fields = ("phone",)
+6
View File
@@ -0,0 +1,6 @@
from django.urls import path
from . import views
urlpatterns = [
path('profile', views.ProfileView.as_view()),
]
+20 -1
View File
@@ -1,3 +1,22 @@
from django.shortcuts import render
from rest_framework.views import APIView
from .serializers import ProfileSerializer
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from rest_framework.response import Response
class ProfileView(APIView):
serializer_class = ProfileSerializer
permission_classes = [IsAuthenticated]
# Create your views here.
def get(self, request):
user_ser = self.serializer_class(instance=request.user)
return Response(user_ser.data, status=status.HTTP_200_OK)
def patch(self, request):
user = request.user
user_ser = self.serializer_class(user, data=request.data, partial=True)
if user_ser.is_valid():
user_ser.save()
return Response(user_ser.data)
return Response(user_ser.errors, status=status.HTTP_400_BAD_REQUEST)
+25 -3
View File
@@ -94,7 +94,9 @@ INSTALLED_APPS = [
'rest_framework.authtoken',
'djoser',
# custom apps
'product'
'product',
'account',
'entertainment',
]
MIDDLEWARE = [
@@ -278,7 +280,7 @@ UNFOLD = {
{
"title": _("محصولات"),
"icon": "redeem",
"link": reverse_lazy("admin:product_product_changelist"),
"link": reverse_lazy("admin:product_productmodel_changelist"),
},
# esm category model ro lower case bezar inja amir
@@ -297,11 +299,31 @@ UNFOLD = {
],
},
{
"title": _("بخش کاربران و مشتریان"),
"separator": True,
"collapsible": True,
"items": [
{
"title": _("users"),
"icon": "person",
"link": reverse_lazy("admin:account_user_changelist"),
},
],
},
],
},
}
AUTH_USER_MODEL = 'account.User'
def environment_callback(request):
return ["Development", "warning"]
+2
View File
@@ -5,6 +5,7 @@ from drf_spectacular.views import SpectacularSwaggerView, SpectacularAPIView
from django.conf import settings
from rest_framework_simplejwt.views import TokenObtainPairView,TokenRefreshView
from product import views
urlpatterns = [
# djoser
@@ -18,6 +19,7 @@ urlpatterns = [
path('schema/', SpectacularAPIView.as_view(), name='schema'),
# path('comment/<int:pk>', views.CommentView.as_view(), name='comment-list'),
path('products/', include('product.urls')),
path('accounts/', include('account.urls')),
path('', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
]
@@ -0,0 +1,141 @@
# Generated by Django 5.1.2 on 2024-12-13 17:49
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='abjad',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('word', models.TextField(verbose_name='صورت ی سوال')),
('image', models.ImageField(blank=True, null=True, upload_to='media/', verbose_name='عکس بازی افتابه')),
('difficulty_type', models.CharField(choices=[('hard', 'سخت'), ('normal', 'متوسط'), ('easy', 'اسون')], max_length=13, verbose_name='سختی')),
('answer', models.CharField(max_length=30, verbose_name='جواب')),
('option2', models.CharField(blank=True, max_length=30, null=True, verbose_name='گزینه ی اشتباه')),
('option3', models.CharField(blank=True, max_length=30, null=True, verbose_name='گزینه ی اشتباه')),
('option4', models.CharField(blank=True, max_length=30, null=True, verbose_name='گزینه ی اشتباه')),
],
options={
'verbose_name': 'سوال ابجد',
'verbose_name_plural': 'سوالات ابجد',
},
),
migrations.CreateModel(
name='challenge',
fields=[
('type', models.CharField(choices=[('map', 'نقشه ی گنج'), ('prize', 'جوایز')], max_length=30, primary_key=True, serialize=False, verbose_name='نوع چالش')),
('image', models.ImageField(upload_to='media/', verbose_name='عکس')),
('link', models.URLField(verbose_name='لینک')),
('text', models.TextField(verbose_name='متن توضیحات')),
('button_text', models.CharField(max_length=40, verbose_name='متن دکمه')),
],
options={
'verbose_name': 'چالش',
'verbose_name_plural': 'چالش ها',
},
),
migrations.CreateModel(
name='Dare',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lang1', models.CharField(max_length=200, verbose_name='فارسی')),
('is_for_adults', models.BooleanField(verbose_name='+18 سوال')),
],
options={
'verbose_name': 'شجاعت',
'verbose_name_plural': 'شجاعت ها',
},
),
migrations.CreateModel(
name='MovieCategory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=40, verbose_name='نام دسته بندی')),
],
options={
'verbose_name': 'دسته بندی قیلم',
'verbose_name_plural': 'دسته بندی فیلم ها',
},
),
migrations.CreateModel(
name='UploadParent',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=300, verbose_name='نام')),
('message_id', models.CharField(max_length=40, verbose_name='ای دی پیام تلگرام')),
],
),
migrations.CreateModel(
name='MusicCategory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=40, verbose_name='نام دسته بندی')),
],
options={
'verbose_name': 'دسته بندی موزیک',
'verbose_name_plural': 'دسته بندی موزیک ها',
},
),
migrations.CreateModel(
name='Truth',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lang1', models.CharField(max_length=200, verbose_name='فارسی')),
('is_for_adults', models.BooleanField(verbose_name='+18 سوال')),
],
options={
'verbose_name': 'حقیقت',
'verbose_name_plural': 'حقیقت ها',
},
),
migrations.CreateModel(
name='Would_you_rather',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lang1', models.CharField(max_length=200, verbose_name='فارسی')),
('is_for_adults', models.BooleanField(verbose_name='+18 سوال')),
],
options={
'verbose_name': 'ترجیح میدی',
'verbose_name_plural': 'ترجیح میدی ها',
},
),
migrations.CreateModel(
name='MovieModel',
fields=[
('uploadparent_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='entertainment.uploadparent')),
('description', models.CharField(blank=True, max_length=4000, null=True, verbose_name='توضیحات فیلم')),
('receommended', models.BooleanField(default=False, verbose_name='پیشنهادی')),
('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='entertainment.moviecategory', verbose_name='دسته بندی')),
],
options={
'verbose_name': 'مدل فیلم',
'verbose_name_plural': 'مدل فیلم ها',
},
bases=('entertainment.uploadparent',),
),
migrations.CreateModel(
name='MusicModel',
fields=[
('uploadparent_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='entertainment.uploadparent')),
('lyric', models.CharField(blank=True, max_length=4000, null=True, verbose_name='متن اهنگ')),
('singer', models.CharField(blank=True, max_length=300, null=True, verbose_name='خواننده')),
('trand', models.BooleanField(default=False, verbose_name='ترند')),
('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='entertainment.musiccategory', verbose_name='دسته بندی')),
],
options={
'verbose_name': 'مدل اهنگ',
'verbose_name_plural': 'مدل اهنگ ها',
},
bases=('entertainment.uploadparent',),
),
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 775 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
from django.db import models
from django.utils.text import slugify
from django.contrib.auth.models import User
from account.models import User
from django.urls import reverse
class CategoryModel(models.Model):