backend merge
This commit is contained in:
@@ -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',
|
||||
),
|
||||
]
|
||||
@@ -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.
|
||||
|
||||
@@ -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",)
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('profile', views.ProfileView.as_view()),
|
||||
]
|
||||
@@ -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]
|
||||
|
||||
def get(self, request):
|
||||
user_ser = self.serializer_class(instance=request.user)
|
||||
return Response(user_ser.data, status=status.HTTP_200_OK)
|
||||
|
||||
# Create your views here.
|
||||
|
||||
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)
|
||||
@@ -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
|
||||
@@ -296,12 +298,32 @@ 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"]
|
||||
|
||||
|
||||
@@ -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,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):
|
||||
|
||||
Reference in New Issue
Block a user