Browse Source

first commit

ilya_shyian 1 year ago
commit
b8a83cef9c
62 changed files with 1581 additions and 0 deletions
  1. 9 0
      .gitignore
  2. 9 0
      config/gunicorn/dev.py
  3. 18 0
      config/gunicorn/prod.py
  4. 22 0
      manage.py
  5. 9 0
      requirements.txt
  6. 0 0
      store_back/__init__.py
  7. 0 0
      store_back/apps/authAPI/__init__.py
  8. 0 0
      store_back/apps/authAPI/admin.py
  9. 5 0
      store_back/apps/authAPI/apps.py
  10. 9 0
      store_back/apps/authAPI/forms.py
  11. 45 0
      store_back/apps/authAPI/migrations/0001_initial.py
  12. 0 0
      store_back/apps/authAPI/migrations/__init__.py
  13. 9 0
      store_back/apps/authAPI/models.py
  14. 20 0
      store_back/apps/authAPI/serializers.py
  15. 16 0
      store_back/apps/authAPI/urls.py
  16. 26 0
      store_back/apps/authAPI/views.py
  17. 0 0
      store_back/apps/categories/__init__.py
  18. 7 0
      store_back/apps/categories/admin.py
  19. 5 0
      store_back/apps/categories/apps.py
  20. 26 0
      store_back/apps/categories/migrations/0001_initial.py
  21. 19 0
      store_back/apps/categories/migrations/0002_alter_category_parent.py
  22. 19 0
      store_back/apps/categories/migrations/0003_alter_category_parent.py
  23. 0 0
      store_back/apps/categories/migrations/__init__.py
  24. 13 0
      store_back/apps/categories/models.py
  25. 26 0
      store_back/apps/categories/serializers.py
  26. 14 0
      store_back/apps/categories/urls.py
  27. 133 0
      store_back/apps/categories/views.py
  28. 0 0
      store_back/apps/goods/__init__.py
  29. 10 0
      store_back/apps/goods/admin.py
  30. 5 0
      store_back/apps/goods/apps.py
  31. 34 0
      store_back/apps/goods/migrations/0001_initial.py
  32. 27 0
      store_back/apps/goods/migrations/0002_alter_good_amount_remove_good_images_good_images.py
  33. 19 0
      store_back/apps/goods/migrations/0003_good_date.py
  34. 0 0
      store_back/apps/goods/migrations/__init__.py
  35. 22 0
      store_back/apps/goods/models.py
  36. 28 0
      store_back/apps/goods/serializers.py
  37. 18 0
      store_back/apps/goods/urls.py
  38. 137 0
      store_back/apps/goods/views.py
  39. 0 0
      store_back/apps/orders/__init__.py
  40. 10 0
      store_back/apps/orders/admin.py
  41. 5 0
      store_back/apps/orders/apps.py
  42. 39 0
      store_back/apps/orders/migrations/0001_initial.py
  43. 19 0
      store_back/apps/orders/migrations/0002_alter_ordergoods_order.py
  44. 18 0
      store_back/apps/orders/migrations/0003_rename_ordergoods_ordergood.py
  45. 19 0
      store_back/apps/orders/migrations/0004_alter_order_date.py
  46. 23 0
      store_back/apps/orders/migrations/0005_ordergood_adress_ordergood_delivery.py
  47. 41 0
      store_back/apps/orders/migrations/0006_remove_ordergood_adress_remove_ordergood_delivery_and_more.py
  48. 22 0
      store_back/apps/orders/migrations/0007_remove_order_adress_order_address.py
  49. 0 0
      store_back/apps/orders/migrations/__init__.py
  50. 31 0
      store_back/apps/orders/models.py
  51. 16 0
      store_back/apps/orders/permissions.py
  52. 22 0
      store_back/apps/orders/serializers.py
  53. 14 0
      store_back/apps/orders/urls.py
  54. 158 0
      store_back/apps/orders/views.py
  55. 16 0
      store_back/asgi.py
  56. 2 0
      store_back/dev.py
  57. 9 0
      store_back/prod.py
  58. 179 0
      store_back/settings copy.py
  59. 123 0
      store_back/settings.py
  60. 19 0
      store_back/urls copy.py
  61. 21 0
      store_back/urls.py
  62. 16 0
      store_back/wsgi.py

+ 9 - 0
.gitignore

@@ -0,0 +1,9 @@
+*.sqlite3
+*.pyc
+__pycache__
+*.jpg
+*.jpeg
+*.png
+db.sqlite3
+env
+staticfiles

+ 9 - 0
config/gunicorn/dev.py

@@ -0,0 +1,9 @@
+wsgi_app = "diploma.wsgi:application"
+loglevel = "debug"
+workers = 1
+bind = "0.0.0.0:8000"
+reload = True
+accesslog = errorlog = "/var/log/gunicorn/dev.log"
+capture_output = True
+pidfile = "/var/run/gunicorn/dev.pid"
+daemon = True

+ 18 - 0
config/gunicorn/prod.py

@@ -0,0 +1,18 @@
+
+import multiprocessing
+
+# Django WSGI application path in pattern MODULE_NAME:VARIABLE_NAME
+wsgi_app = "diploma.wsgi:application"
+# The number of worker processes for handling requests
+workers = multiprocessing.cpu_count() * 2 + 1
+# The socket to bind
+bind = "0.0.0.0:8000"
+# Write access and error info to /var/log
+accesslog = "/var/log/gunicorn/access.log"
+errorlog = "/var/log/gunicorn/error.log"
+# Redirect stdout/stderr to log file
+capture_output = True
+# PID file so you can easily fetch process ID
+pidfile = "/var/run/gunicorn/prod.pid"
+# Daemonize the Gunicorn process (detach & enter background)
+daemon = True

+ 22 - 0
manage.py

@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+    """Run administrative tasks."""
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'store_back.settings')
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+    main()

+ 9 - 0
requirements.txt

@@ -0,0 +1,9 @@
+asgiref==3.5.1
+Django==4.0.4
+djangorestframework==3.13.1
+djangorestframework-simplejwt==5.1.0
+Markdown==3.3.7
+Pillow==9.1.0
+PyJWT==2.4.0
+pytz==2022.1
+sqlparse==0.4.2

+ 0 - 0
store_back/__init__.py


+ 0 - 0
store_back/apps/authAPI/__init__.py


+ 0 - 0
store_back/apps/authAPI/admin.py


+ 5 - 0
store_back/apps/authAPI/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class AuthAPIConfig(AppConfig):
+    name = 'authAPI'

+ 9 - 0
store_back/apps/authAPI/forms.py

@@ -0,0 +1,9 @@
+from django import forms
+from django.contrib.auth.forms import UserCreationForm
+from .models import CustomUser
+
+
+class RegisterForm(UserCreationForm):
+    class Meta:
+        model = CustomUser
+        fields = ["username", "password1", "password2"]

+ 45 - 0
store_back/apps/authAPI/migrations/0001_initial.py

@@ -0,0 +1,45 @@
+# Generated by Django 4.0.4 on 2022-06-21 14:32
+
+import django.contrib.auth.models
+import django.contrib.auth.validators
+from django.db import migrations, models
+import django.utils.timezone
+import uuid
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('auth', '0012_alter_user_first_name_max_length'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='CustomUser',
+            fields=[
+                ('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')),
+                ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
+                ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
+                ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
+                ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
+                ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
+                ('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')),
+                ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=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={
+                'verbose_name': 'user',
+                'verbose_name_plural': 'users',
+                'abstract': False,
+            },
+            managers=[
+                ('objects', django.contrib.auth.models.UserManager()),
+            ],
+        ),
+    ]

+ 0 - 0
store_back/apps/authAPI/migrations/__init__.py


+ 9 - 0
store_back/apps/authAPI/models.py

@@ -0,0 +1,9 @@
+import uuid
+from django.contrib.auth.models import AbstractUser
+from django.db import models
+
+
+class CustomUser(AbstractUser):
+    _id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+    def __str__(self):
+        return self.username

+ 20 - 0
store_back/apps/authAPI/serializers.py

@@ -0,0 +1,20 @@
+from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
+import datetime
+class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
+
+    @classmethod
+    def get_token(cls, user):
+        token = super().get_token(user)
+
+        # Add custom claims
+        token['iat'] = datetime.datetime.now()
+        token["sub"] = {
+            "acl":["anon"],
+        }
+        if user._id:
+            token["sub"]["acl"].append(str(user._id))
+            if  user.is_superuser:
+                token["sub"]["acl"].append("admin")
+            token["sub"]["login"] = user.username
+            token["sub"]["_id"] = str(user._id)
+        return token

+ 16 - 0
store_back/apps/authAPI/urls.py

@@ -0,0 +1,16 @@
+from django.urls import path
+from . import views
+
+from rest_framework_simplejwt.views import (  TokenRefreshView)
+from .views import MyTokenObtainPairView
+
+
+app_name = 'auth'
+
+#Шаблоны ссылок данного приложения
+urlpatterns = [
+    path('token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
+    path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
+    path('register/',views.register, name = "register"),
+
+]

+ 26 - 0
store_back/apps/authAPI/views.py

@@ -0,0 +1,26 @@
+from .serializers import MyTokenObtainPairSerializer
+from django.http import HttpResponse, JsonResponse
+from django.views.decorators.csrf import csrf_exempt
+from rest_framework.decorators import api_view, permission_classes,authentication_classes
+from rest_framework_simplejwt.views import TokenObtainPairView
+from .forms import RegisterForm
+from .models import CustomUser
+
+
+class MyTokenObtainPairView(TokenObtainPairView):
+    serializer_class = MyTokenObtainPairSerializer
+
+
+@csrf_exempt
+def register(request):
+    if request.method == 'POST':
+        form = RegisterForm(request.POST)
+        if form.is_valid():
+            newUser = form.save()
+
+            return JsonResponse({"data":{"_id":newUser._id}}, safe=False)
+        else:
+            print(form.errors)
+            return JsonResponse({"errors":[{"message":"Невірні дані"}]}, safe=False)
+
+    return JsonResponse({"errors":[{"message":"Invalid method, method must be POST"}]}, safe=False)

+ 0 - 0
store_back/apps/categories/__init__.py


+ 7 - 0
store_back/apps/categories/admin.py

@@ -0,0 +1,7 @@
+from django.contrib import admin
+from .models import Category
+
+@admin.register( Category)
+class CategoryAdmin(admin.ModelAdmin):
+    pass
+

+ 5 - 0
store_back/apps/categories/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class CategoriesConfig(AppConfig):
+    name = 'categories'

+ 26 - 0
store_back/apps/categories/migrations/0001_initial.py

@@ -0,0 +1,26 @@
+# Generated by Django 4.0.4 on 2022-05-18 13:53
+
+from django.db import migrations, models
+import django.db.models.deletion
+import uuid
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('goods', '0002_alter_good_amount_remove_good_images_good_images'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Category',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('name', models.CharField(max_length=200, verbose_name='name')),
+                ('goods', models.ManyToManyField(blank=True, related_name='categories', to='goods.good')),
+                ('parent', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='subcategories', to='categories.category')),
+            ],
+        ),
+    ]

+ 19 - 0
store_back/apps/categories/migrations/0002_alter_category_parent.py

@@ -0,0 +1,19 @@
+# Generated by Django 4.0.4 on 2022-05-18 14:32
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('categories', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='category',
+            name='parent',
+            field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subcategories', to='categories.category'),
+        ),
+    ]

+ 19 - 0
store_back/apps/categories/migrations/0003_alter_category_parent.py

@@ -0,0 +1,19 @@
+# Generated by Django 4.0.4 on 2022-05-18 14:33
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('categories', '0002_alter_category_parent'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='category',
+            name='parent',
+            field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subcategories', to='categories.category'),
+        ),
+    ]

+ 0 - 0
store_back/apps/categories/migrations/__init__.py


+ 13 - 0
store_back/apps/categories/models.py

@@ -0,0 +1,13 @@
+from django.db import models
+from goods.models import Good
+import uuid
+
+
+
+
+class Category(models.Model):
+    _id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+    name = models.CharField('name', max_length = 200)
+    parent =models.ForeignKey('self',default=None,null=True,blank=True,related_name = "subcategories", on_delete = models.CASCADE)
+    goods = models.ManyToManyField(Good,related_name ="categories", blank = True)
+

+ 26 - 0
store_back/apps/categories/serializers.py

@@ -0,0 +1,26 @@
+
+from rest_framework import serializers
+from .models import Category
+from goods.serializers import GoodSerializer
+
+
+class SubCategorySerializer(serializers.ModelSerializer):
+    class Meta:
+        model =  Category
+        fields = ['_id','name']
+
+class CategorySerializer(serializers.ModelSerializer):
+    parent = SubCategorySerializer()
+    subcategories =SubCategorySerializer(many=True)
+    goods = serializers.SerializerMethodField()
+
+    def get_goods(self, instance):
+        goods = instance.goods.all().order_by(self.context.get("goods_order_by","_id"))
+        return GoodSerializer(goods, many=True).data
+
+    class Meta:
+        model =  Category
+        fields = ['_id','name','parent','subcategories','goods']
+
+
+

+ 14 - 0
store_back/apps/categories/urls.py

@@ -0,0 +1,14 @@
+from django.urls import path
+from . import views
+
+
+app_name = 'categories'
+
+#Шаблоны ссылок данного приложения
+urlpatterns = [
+	path('categories/',views.category_list, name = 'category_list'),
+    path('categories/<str:_id>/',views.category_detail, name = 'category_detail'),
+    path('category/<str:_id>/delete/',views.category_delete, name = 'category_delete'),
+    path('category/',views.category_upsert, name = 'category_upsert'),
+
+]

+ 133 - 0
store_back/apps/categories/views.py

@@ -0,0 +1,133 @@
+from django.http import HttpResponse, JsonResponse
+from django.views.decorators.csrf import csrf_exempt
+from rest_framework.parsers import JSONParser
+from .models import Category
+from .serializers import CategorySerializer
+import json
+from rest_framework.decorators import api_view, permission_classes,authentication_classes
+from rest_framework.permissions import IsAdminUser,IsAdminUser
+from rest_framework_simplejwt.authentication import JWTAuthentication
+from django.db.models import Q
+
+
+@csrf_exempt
+@api_view(["GET"])
+def category_list(request,):
+    skip = int(request.GET.get("skip",0))
+    limit = int(request.GET.get("limit",50))
+    isRoot = int(request.GET.get("root",0))
+    text = request.GET.get("text","")
+    orderBy = request.GET.get("orderBy","_id")
+
+
+    try:
+        if text:
+            categories = Category.objects.filter(Q(name__contains = text) ).order_by(orderBy)[skip:skip+limit]
+        elif isRoot:
+            categories = Category.objects.filter(parent=None).order_by(orderBy)[skip:skip+limit]
+        else:
+            categories  = Category.objects.all().order_by(orderBy)[skip:skip+limit]
+
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Не вірні дані"}]}, safe=False)
+
+
+    serializer = CategorySerializer(categories, many=True)
+
+    return JsonResponse({"data":serializer.data}, safe=False)
+
+
+@csrf_exempt
+@api_view(["GET"])
+def category_detail(request,_id):
+    try:
+        goods_order_by = request.GET.get("orderBy","_id")
+        goods_limit = request.GET.get("limit",20)
+        goods_skip = request.GET.get("skip",0)
+    except:
+        return JsonResponse({"errors":[{"message":"Невірні параметри запиту"}]}, safe=False)
+    try:
+        category  = Category.objects.get(_id = _id)
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Категорию не знайдено"}]}, safe=False)
+
+    if category:
+        serializer = CategorySerializer(category,context = {"goods_order_by":goods_order_by,"goods_limit":goods_limit,"goods_skip":goods_skip})
+        return JsonResponse({"data":serializer.data}, safe=False)
+    else:
+        return JsonResponse({"data":{}}, safe=False)
+
+
+
+
+@csrf_exempt
+@api_view(["POST"])
+@permission_classes((IsAdminUser, ))
+@authentication_classes([JWTAuthentication])
+def category_upsert(request):
+    try:
+        _id = request.POST.get('_id',None)
+        name = request.POST.get("name", "")
+        subcategories =  json.loads(request.POST.get("subcategories", "[]"))
+        parent = request.POST.get("parent", None)
+        goods = json.loads(request.POST.get("goods","[]"))
+    except:
+        return JsonResponse({"errors":[{"message":"Не вірні дані"}]}, safe=False)
+    if _id :
+        try:
+            category = Category.objects.get(_id = _id)
+        except Exception as e:
+            return JsonResponse({"errors":[{"message":"Не вірні дані"}]}, safe=False)
+
+        category.name = name
+
+    else:
+        category = Category.objects.create(name=name)
+
+    if parent:
+        print(parent)
+        category.parent = Category.objects.get(_id=json.loads(parent)["_id"])
+
+    category.goods.clear()
+    for good in goods:
+        category.goods.add(good["_id"])
+
+    category.subcategories.clear()
+    for subcategory in subcategories:
+        try:
+            category.subcategories.add(Category.objects.get(_id = subcategory["_id"]))
+        except:
+            return JsonResponse({"errors":[{"message":"Батькову категорію не знайдено"}]}, safe=False)
+    if category:
+        category.save()
+        serializer = CategorySerializer(category)
+        return JsonResponse({"data":serializer.data}, safe=False)
+    else:
+        return JsonResponse({"data":{}}, safe=False)
+
+
+
+@csrf_exempt
+@api_view(['GET'])
+@authentication_classes([JWTAuthentication])
+@permission_classes((IsAdminUser, ))
+def category_delete(request,_id):
+
+    try:
+        category  = Category.objects.get(_id = _id)
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Категорію не знайдено"}]}, safe=False)
+
+    if category:
+        category.delete()
+        return JsonResponse({"data":{"_id":_id}}, safe=False)
+
+    return JsonResponse({"data":{}}, safe=False)
+
+
+
+
+
+
+
+

+ 0 - 0
store_back/apps/goods/__init__.py


+ 10 - 0
store_back/apps/goods/admin.py

@@ -0,0 +1,10 @@
+from django.contrib import admin
+from .models import Good, Image
+
+@admin.register(Good)
+class GoodAdmin(admin.ModelAdmin):
+    pass
+
+@admin.register(Image)
+class ImageAdmin(admin.ModelAdmin):
+    pass

+ 5 - 0
store_back/apps/goods/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class GoodsConfig(AppConfig):
+    name = 'goods'

+ 34 - 0
store_back/apps/goods/migrations/0001_initial.py

@@ -0,0 +1,34 @@
+# Generated by Django 4.0.4 on 2022-05-17 15:40
+
+from django.db import migrations, models
+import django.db.models.deletion
+import uuid
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Image',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('url', models.ImageField(upload_to='uploads/')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Good',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('name', models.CharField(max_length=200, verbose_name='name')),
+                ('description', models.CharField(max_length=1000, verbose_name='description')),
+                ('price', models.IntegerField(default=0, verbose_name='price')),
+                ('amount', models.IntegerField(default=0, verbose_name='price')),
+                ('images', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to='goods.image')),
+            ],
+        ),
+    ]

+ 27 - 0
store_back/apps/goods/migrations/0002_alter_good_amount_remove_good_images_good_images.py

@@ -0,0 +1,27 @@
+# Generated by Django 4.0.4 on 2022-05-17 15:50
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('goods', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='good',
+            name='amount',
+            field=models.IntegerField(default=0, verbose_name='amount'),
+        ),
+        migrations.RemoveField(
+            model_name='good',
+            name='images',
+        ),
+        migrations.AddField(
+            model_name='good',
+            name='images',
+            field=models.ManyToManyField(blank=True, related_name='goods', to='goods.image'),
+        ),
+    ]

+ 19 - 0
store_back/apps/goods/migrations/0003_good_date.py

@@ -0,0 +1,19 @@
+# Generated by Django 4.0.4 on 2022-05-30 20:08
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('goods', '0002_alter_good_amount_remove_good_images_good_images'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='good',
+            name='date',
+            field=models.DateTimeField(default=django.utils.timezone.now),
+        ),
+    ]

+ 0 - 0
store_back/apps/goods/migrations/__init__.py


+ 22 - 0
store_back/apps/goods/models.py

@@ -0,0 +1,22 @@
+from django.db import models
+import uuid
+from django.utils import timezone
+
+
+
+
+class Image(models.Model):
+    _id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+    url = models.ImageField(upload_to ='uploads/')
+
+
+
+class Good(models.Model):
+    _id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+    name = models.CharField('name', max_length = 200)
+    description = models.CharField('description', max_length = 1000)
+    price = models.IntegerField("price", default=0)
+    amount = models.IntegerField("amount", default=0)
+    images = models.ManyToManyField(Image,related_name ="goods", blank = True)
+    date = models.DateTimeField(default=timezone.now)
+

+ 28 - 0
store_back/apps/goods/serializers.py

@@ -0,0 +1,28 @@
+
+from rest_framework import serializers
+from .models import Good, Image
+from categories.models import Category
+
+
+class SubCategorySerializer(serializers.ModelSerializer):
+    class Meta:
+        model =  Category
+        fields = ['_id','name']
+
+
+class ImageSerializer(serializers.ModelSerializer):
+    
+    class Meta:
+        model =  Image
+        fields = ['_id','url']
+
+
+
+class GoodSerializer(serializers.ModelSerializer):
+    images = ImageSerializer(many=True)
+    categories =  SubCategorySerializer(many=True)
+    class Meta:
+        model =  Good
+        fields = ['_id',"name","price","amount","description","images","categories"]
+
+

+ 18 - 0
store_back/apps/goods/urls.py

@@ -0,0 +1,18 @@
+from django.urls import path
+from . import views
+
+
+app_name = 'goods'
+
+#Шаблоны ссылок данного приложения
+urlpatterns = [
+	path('goods/',views.good_list, name = 'good_list'),
+    path('goods/<str:_id>/',views.good_detail, name = 'good_detail'),
+    path('good/<str:_id>/delete/',views.good_delete, name = 'good_delete'),
+    path('good/',views.good_upsert, name = 'good_upsert'),
+    path('upload/',views.image_upsert, name = 'image_upsert')
+    # path('add-rating/',views.AddStarRating.as_view(),name = "add_rating"),
+    # path('<slug:slug>/',views.BookDetailView.as_view(), name = 'book_detail'),
+    # path('<slug:slug>/<int:page_id>/',views.Page.as_view(), name = 'page'),
+    # path('ajax/show_more_books/<int:page>/',views.ShowMoreBooks.as_view(), name = 'show_more_books'),
+]

+ 137 - 0
store_back/apps/goods/views.py

@@ -0,0 +1,137 @@
+from django.http import HttpResponse, JsonResponse
+from django.views.decorators.csrf import csrf_exempt
+from rest_framework.parsers import JSONParser
+from .models import Good, Image
+from .serializers import GoodSerializer, ImageSerializer
+from django.db.models import Count
+import json
+from rest_framework.decorators import api_view, permission_classes,authentication_classes
+from rest_framework.permissions import IsAdminUser,IsAdminUser
+from rest_framework_simplejwt.authentication import JWTAuthentication
+from django.db.models import Q
+
+@csrf_exempt
+@api_view(['GET'])
+def good_list(request,):
+
+    skip = int(request.GET.get("skip",0))
+    limit = int(request.GET.get("limit",50))
+    popular = int(request.GET.get("pupular",0))
+    text = request.GET.get("text","")
+    orderBy = request.GET.get("orderBy","_id")
+
+    try:
+        if text:
+            goods  = Good.objects.filter(Q(name__contains = text) | Q(description__contains = text)  ).order_by(orderBy)[skip:skip+limit]
+        elif popular:
+            goods  = Good.objects.annotate(order_count=Count('orderGoods')).order_by("order_count")[skip:skip+limit]
+        else:
+            goods  = Good.objects.all().order_by(orderBy)[skip:skip+limit]
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Не вірні дані запиту"}]}, safe=False)
+
+    serializer = GoodSerializer(goods, many=True)
+
+    return JsonResponse({"data":serializer.data}, safe=False)
+
+
+@csrf_exempt
+@api_view(['GET'])
+def good_detail(request,_id):
+    try:
+        good  = Good.objects.get(_id = _id)
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Товар не знайдено"}]}, safe=False)
+
+    if good:
+        serializer = GoodSerializer(good)
+        return JsonResponse({"data":serializer.data}, safe=False)
+    else:
+        return JsonResponse({"data":{}}, safe=False)
+
+@csrf_exempt
+@api_view(['GET'])
+@authentication_classes([JWTAuthentication])
+@permission_classes((IsAdminUser, ))
+def good_delete(request,_id):
+
+    try:
+        good  = Good.objects.get(_id = _id)
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Товар не знайдено"}]}, safe=False)
+
+    if good:
+        good.delete()
+        return JsonResponse({"data":{"_id":_id}}, safe=False)
+
+    return JsonResponse({"data":{}}, safe=False)
+
+
+
+
+
+@csrf_exempt
+@api_view(['POST'])
+@authentication_classes([JWTAuthentication])
+@permission_classes((IsAdminUser, ))
+def good_upsert(request):
+    try:
+        _id = request.POST.get('_id',None)
+        name = request.POST.get("name", "")
+        price =  request.POST.get("price", "").replace(" ","")
+        description = request.POST.get("description", "")
+        amount = request.POST.get("amount","").replace(" ","")
+        images = json.loads(request.POST.get("images", "[]"))
+        categories = json.loads(request.POST.get("categories", "[]"))
+
+        if not price.isdigit() or not amount.isdigit():
+            return JsonResponse({"errors":[{"message":"Не вірні дані"}]}, safe=False)
+
+    except:
+        return JsonResponse({"errors":[{"message":"Не вірні дані"}]}, safe=False)
+
+    if _id :
+        try:
+            good  = Good.objects.get(_id = _id)
+        except Exception as e:
+            return JsonResponse({"errors":[{"message":"Не вірні дані запиту"}]}, safe=False)
+        good.description = description
+        good.name = name
+        good.price = price
+        good.amount = amount
+
+    else:
+        good = Good.objects.create(name=name,price=price,amount=amount,description=description)
+
+    good.images.clear()
+    for image in images:
+        good.images.add(image["_id"])
+
+    good.categories.clear()
+    for category in categories:
+        good.categories.add(category["_id"])
+
+    if good:
+        good.save()
+        serializer = GoodSerializer(good)
+        return JsonResponse({"data":serializer.data}, safe=False)
+    else:
+        return JsonResponse({"data":{}}, safe=False)
+
+
+
+
+@csrf_exempt
+@api_view(['POST'])
+@authentication_classes([JWTAuthentication])
+@permission_classes((IsAdminUser, ))
+def image_upsert(request):
+        file = request.FILES.get("photo" , None)
+        if file:
+            image = Image.objects.create(url =file )
+            image.save()
+            serializer = ImageSerializer(image)
+            print(serializer.data)
+            return JsonResponse({"data":serializer.data}, safe=False)
+        else:
+            return JsonResponse({"data":{}}, safe=False)

+ 0 - 0
store_back/apps/orders/__init__.py


+ 10 - 0
store_back/apps/orders/admin.py

@@ -0,0 +1,10 @@
+from django.contrib import admin
+from .models import Order, OrderGood
+
+@admin.register(Order)
+class OrderAdmin(admin.ModelAdmin):
+    pass
+
+@admin.register(OrderGood)
+class OrderGoodAdmin(admin.ModelAdmin):
+    pass

+ 5 - 0
store_back/apps/orders/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class OrdersConfig(AppConfig):
+    name = 'orders'

+ 39 - 0
store_back/apps/orders/migrations/0001_initial.py

@@ -0,0 +1,39 @@
+# Generated by Django 4.0.4 on 2022-05-18 13:53
+
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+import uuid
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('goods', '0002_alter_good_amount_remove_good_images_good_images'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Order',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('date', models.DateField(default=django.utils.timezone.now)),
+                ('status', models.IntegerField(default=1, verbose_name='status')),
+                ('price', models.IntegerField(default=1, verbose_name='price')),
+                ('phoneNumber', models.CharField(max_length=15, verbose_name='phoneNumber')),
+                ('email', models.CharField(max_length=50, verbose_name='email')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='OrderGoods',
+            fields=[
+                ('_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('price', models.IntegerField(default=1, verbose_name='price')),
+                ('count', models.IntegerField(default=1, verbose_name='count')),
+                ('good', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='goods.good')),
+                ('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orderGoods', to='orders.order')),
+            ],
+        ),
+    ]

+ 19 - 0
store_back/apps/orders/migrations/0002_alter_ordergoods_order.py

@@ -0,0 +1,19 @@
+# Generated by Django 4.0.4 on 2022-05-18 14:54
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orders', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='ordergoods',
+            name='order',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orderGoods', to='orders.order'),
+        ),
+    ]

+ 18 - 0
store_back/apps/orders/migrations/0003_rename_ordergoods_ordergood.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.0.4 on 2022-05-18 17:44
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('goods', '0002_alter_good_amount_remove_good_images_good_images'),
+        ('orders', '0002_alter_ordergoods_order'),
+    ]
+
+    operations = [
+        migrations.RenameModel(
+            old_name='OrderGoods',
+            new_name='OrderGood',
+        ),
+    ]

+ 19 - 0
store_back/apps/orders/migrations/0004_alter_order_date.py

@@ -0,0 +1,19 @@
+# Generated by Django 4.0.4 on 2022-05-18 17:45
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orders', '0003_rename_ordergoods_ordergood'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='order',
+            name='date',
+            field=models.DateTimeField(default=django.utils.timezone.now),
+        ),
+    ]

+ 23 - 0
store_back/apps/orders/migrations/0005_ordergood_adress_ordergood_delivery.py

@@ -0,0 +1,23 @@
+# Generated by Django 4.0.4 on 2022-05-19 18:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orders', '0004_alter_order_date'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='ordergood',
+            name='adress',
+            field=models.CharField(default='-', max_length=150, verbose_name='adress'),
+        ),
+        migrations.AddField(
+            model_name='ordergood',
+            name='delivery',
+            field=models.CharField(default='-', max_length=50, verbose_name='delivery'),
+        ),
+    ]

+ 41 - 0
store_back/apps/orders/migrations/0006_remove_ordergood_adress_remove_ordergood_delivery_and_more.py

@@ -0,0 +1,41 @@
+# Generated by Django 4.0.4 on 2022-05-19 18:47
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orders', '0005_ordergood_adress_ordergood_delivery'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='ordergood',
+            name='adress',
+        ),
+        migrations.RemoveField(
+            model_name='ordergood',
+            name='delivery',
+        ),
+        migrations.AddField(
+            model_name='order',
+            name='adress',
+            field=models.CharField(default='-', max_length=150, verbose_name='adress'),
+        ),
+        migrations.AddField(
+            model_name='order',
+            name='delivery',
+            field=models.CharField(default='-', max_length=50, verbose_name='delivery'),
+        ),
+        migrations.AddField(
+            model_name='order',
+            name='name',
+            field=models.CharField(default='-', max_length=150, verbose_name='name'),
+        ),
+        migrations.AddField(
+            model_name='order',
+            name='surname',
+            field=models.CharField(default='-', max_length=150, verbose_name='surname'),
+        ),
+    ]

+ 22 - 0
store_back/apps/orders/migrations/0007_remove_order_adress_order_address.py

@@ -0,0 +1,22 @@
+# Generated by Django 4.0.4 on 2022-05-19 19:50
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orders', '0006_remove_ordergood_adress_remove_ordergood_delivery_and_more'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='order',
+            name='adress',
+        ),
+        migrations.AddField(
+            model_name='order',
+            name='address',
+            field=models.CharField(default='-', max_length=150, verbose_name='address'),
+        ),
+    ]

+ 0 - 0
store_back/apps/orders/migrations/__init__.py


+ 31 - 0
store_back/apps/orders/models.py

@@ -0,0 +1,31 @@
+from django.db import models
+from goods.models import Good
+from django.utils import timezone
+import uuid
+
+
+class Order(models.Model):
+    _id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+    date = models.DateTimeField(default=timezone.now)
+    status = models.IntegerField("status", default=1)
+    price = models.IntegerField("price", default=1)
+    phoneNumber = models.CharField("phoneNumber", max_length=15)
+    delivery = models.CharField("delivery",max_length=50,default="-")
+    address = models.CharField("address",max_length=150,default="-")
+    name = models.CharField("name",max_length=150,default="-")
+    surname = models.CharField("surname",max_length=150,default="-")
+    email  = models.CharField("email", max_length=50)
+
+
+
+class OrderGood(models.Model):
+    _id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+    good = models.ForeignKey(Good, on_delete=models.CASCADE)
+    price = models.IntegerField("price", default=1)
+    count = models.IntegerField("count", default=1)
+    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="orderGoods",blank=True,null=True)
+
+
+
+
+

+ 16 - 0
store_back/apps/orders/permissions.py

@@ -0,0 +1,16 @@
+from rest_framework.permissions import IsAdminUser
+class OrderUpsertPermission(IsAdminUser):
+    def has_permission(self, request, view):
+        if request.method == 'POST':
+            try:
+                _id = request.POST.get("_id",None)
+            except:
+                return super().has_permission(request, view)
+
+
+            if _id :
+                return super().has_permission(request, view)
+            else:
+                return True
+        else:
+            return False

+ 22 - 0
store_back/apps/orders/serializers.py

@@ -0,0 +1,22 @@
+
+from rest_framework import serializers
+from .models import Order,OrderGood
+from goods.serializers import GoodSerializer
+
+
+
+
+class OrderGoodSertializer(serializers.ModelSerializer):
+    good = GoodSerializer()
+    class Meta:
+        model =  OrderGood
+        fields = ['_id',"price","count","good",]
+
+
+class OrderSerializer(serializers.ModelSerializer):
+    orderGoods = OrderGoodSertializer(many=True)
+    class Meta:
+        model =  Order
+        fields = ['_id',"date","price","status","orderGoods","phoneNumber","email","name","surname","address","delivery"]
+
+

+ 14 - 0
store_back/apps/orders/urls.py

@@ -0,0 +1,14 @@
+from django.urls import path
+from . import views
+
+
+app_name = 'orders'
+
+#Шаблоны ссылок данного приложения
+urlpatterns = [
+	path('orders/',views.order_list, name = 'order_list'),
+    path('orders/<str:_id>/',views.order_detail, name = 'order_detail'),
+    path('order/',views.order_upsert, name = 'order_upsert'),
+    path('order/<str:_id>/delete/',views.order_delete, name = 'order_delete'),
+
+]

+ 158 - 0
store_back/apps/orders/views.py

@@ -0,0 +1,158 @@
+from django.http import HttpResponse, JsonResponse
+from django.views.decorators.csrf import csrf_exempt
+from rest_framework.parsers import JSONParser
+from .models import Order, OrderGood
+from goods.models import Good
+from .serializers import OrderSerializer
+from .permissions import OrderUpsertPermission
+import json
+from rest_framework.decorators import api_view, permission_classes,authentication_classes
+from rest_framework.permissions import IsAdminUser,IsAdminUser
+from rest_framework_simplejwt.authentication import JWTAuthentication
+from django.db.models import Q
+
+
+@csrf_exempt
+@api_view(['GET'])
+@authentication_classes([JWTAuthentication])
+@permission_classes((IsAdminUser, ))
+def order_list(request):
+    try:
+        skip = int(request.GET.get("skip",0))
+        limit = int(request.GET.get("limit",50))
+        orderBy = request.GET.get("orderBy","date")
+        status = int(request.GET.get("status",0))
+    except:
+        return JsonResponse({"errors":[{"message":"Невірні параметри запиту"}]}, safe=False)
+
+    text = request.GET.get("text","")
+    try:
+        if text:
+            orders  = Order.objects.filter(Q(name__contains = text) | Q(email__contains = text) | Q(phoneNumber__contains = text) | Q(surname__contains = text) | Q(_id__contains = text) ).order_by(orderBy)
+        else:
+            orders  = Order.objects.all().order_by(orderBy)
+
+        if status != 0:
+            orders = orders.filter(status = status)
+        serializer = OrderSerializer(orders[skip:skip+limit], many=True)
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Замовлення не знайдено"}]}, safe=False)
+
+    return JsonResponse({"data":serializer.data}, safe=False)
+
+
+@csrf_exempt
+@api_view(["GET"])
+@permission_classes([IsAdminUser])
+@authentication_classes([JWTAuthentication])
+def order_detail(request,_id):
+    try:
+        order = Order.objects.get(_id = _id)
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Замовлення не знайдено"}]}, safe=False)
+
+    order  = Order.objects.get(_id = _id)
+    if order:
+        serializer = OrderSerializer(order)
+        return JsonResponse({"data":serializer.data}, safe=False)
+    else:
+        return JsonResponse({"data":{}}, safe=False)
+
+
+
+@csrf_exempt
+@api_view(['GET'])
+@authentication_classes([JWTAuthentication])
+@permission_classes((IsAdminUser, ))
+def order_delete(request,_id):
+
+    try:
+        order  = Order.objects.get(_id = _id)
+    except Exception as e:
+        return JsonResponse({"errors":[{"message":"Замовлення не знайдено"}]}, safe=False)
+
+    if order:
+        order.delete()
+        return JsonResponse({"data":{"_id":_id}}, safe=False)
+
+    return JsonResponse({"data":{}}, safe=False)
+
+
+
+@csrf_exempt
+@api_view(["POST"])
+@permission_classes([OrderUpsertPermission, ])
+@authentication_classes([JWTAuthentication])
+def order_upsert(request):
+    orderPrice = 0
+    try:
+        _id = request.POST.get('_id',None)
+        name = request.POST.get("name", "-")
+        orderGoods=  json.loads(request.POST.get("orderGoods", "[]"))
+        email = request.POST.get("email", "")
+        phoneNumber = request.POST.get("phoneNumber", "-")
+        if _id:
+            status = request.POST.get("status", "1")
+        else:
+            status = "1"
+        delivery = request.POST.get("delivery", "-")
+        address = request.POST.get("address", "-")
+        surname = request.POST.get("surname", "-")
+    except:
+        return JsonResponse({"errors":[{"message":"Не вірні дані"}]}, safe=False)
+
+
+    if len(orderGoods) == 0:
+        return JsonResponse({"errors":[{"message":"Товари відсутні"}]}, safe=False)
+
+    if _id :
+        order = Order.objects.get(_id = _id)
+        order.email = email
+        order.name = name
+        order.surname = surname
+        order.address = address
+        order.delivery = delivery
+        order.phoneNumber = phoneNumber
+
+
+    else:
+        order = Order.objects.create(email=email,phoneNumber=phoneNumber,status=status,address=address,delivery=delivery,name = name,surname =surname)
+
+
+    for orderGood in order.orderGoods.all():
+        if order.status != 4:
+            orderGood.good.amount += orderGood.count
+            orderGood.good.save()
+
+    order.orderGoods.clear()
+    for orderGood in orderGoods:
+        try:
+            good = Good.objects.get(_id = orderGood.get("good")["_id"])
+        except:
+            return JsonResponse({"errors":[{"message":"Товар не знайдено"}]}, safe=False)
+
+        count = orderGood.get("count")
+        if int(good.amount) - int(count) >= 0:
+            price = int(count) * int(good.price)
+            orderGoodToSave = OrderGood.objects.create(price = price, count = count, good = good)
+            orderGoodToSave.save()
+            order.orderGoods.add(orderGoodToSave)
+            orderPrice+=int(price)
+
+            if int(status) != 4:
+                good.amount = int(good.amount) - int(count)
+                good.save()
+
+        else:
+            return JsonResponse({"errors":[{"message":f"{good.name}:Недостатньо товару!"}]}, safe=False)
+
+    order.price = orderPrice
+    order.status = status
+
+
+    if order:
+        order.save()
+        serializer = OrderSerializer(order)
+        return JsonResponse({"data":serializer.data}, safe=False)
+    else:
+        return JsonResponse({"data":{}}, safe=False)

+ 16 - 0
store_back/asgi.py

@@ -0,0 +1,16 @@
+"""
+ASGI config for store_back project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'store_back.settings')
+
+application = get_asgi_application()

+ 2 - 0
store_back/dev.py

@@ -0,0 +1,2 @@
+CSRF_TRUSTED_ORIGINS = ["http://127.0.0.1:8000"]
+ALLOWED_HOSTS = ["*"]

+ 9 - 0
store_back/prod.py

@@ -0,0 +1,9 @@
+import os,sys
+from datetime import timedelta
+from .settings import SECRET_KEY,BASE_DIR,PROJECT_DIR,DEBUG
+
+
+CSRF_TRUSTED_ORIGINS = []
+ALLOWED_HOSTS = []
+SECURE_HSTS_SECONDS = 2_592_000
+

+ 179 - 0
store_back/settings copy.py

@@ -0,0 +1,179 @@
+
+
+import os,sys
+from datetime import timedelta
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+PROJECT_ROOT = os.path.dirname(__file__)
+sys.path.insert(0,os.path.join(PROJECT_ROOT,'apps'))
+
+AUTH_USER_MODEL = 'authAPI.CustomUser'
+
+try:
+    if os.environ['debug'] == 'False':
+        DEBUG = False
+    else:
+        DEBUG = True
+except:
+    DEBUG = True
+
+
+
+
+if DEBUG:
+    SECRET_KEY = 'django-insecure-e*vqkvk_c%y&(v-^isb_%uwxq#y4eun3xhf4al_5f_)&14e5f0'
+else:
+    try:
+        SECRET_KEY = os.environ["SECRET_KEY"]
+    except KeyError as e:
+        raise RuntimeError("Could not find a SECRET_KEY in environment") from e
+    from .prod import *
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'rest_framework',
+    'goods.apps.GoodsConfig',
+    'authAPI.apps.AuthAPIConfig',
+    'orders.apps.OrdersConfig',
+    'categories.apps.CategoriesConfig',
+]
+
+MIDDLEWARE = [
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'store_back.urls'
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'store_back.wsgi.application'
+
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/4.0/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_TZ = True
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.postgresql_psycopg2',
+        'NAME': 'dfi11snf6cpamj',
+        'USER' : 'qvkowaptdjfexz',
+        'PASSWORD' : '3ef6f3a16c918da406cd2b388042a45080ff7f9dd10d5f9cc1df0ec0eca8ab7a',
+        'HOST' : 'ec2-52-48-159-67.eu-west-1.compute.amazonaws.com',
+        'PORT' : '5432',
+    }
+}
+
+
+
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/4.0/howto/static-files/
+
+STATIC_ROOT = os.path.join(BASE_DIR, 'static')
+STATIC_URL = 'api/static/'
+
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')
+MEDIA_URL = 'api/media/'
+
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
+
+
+
+SIMPLE_JWT = {
+    'ACCESS_TOKEN_LIFETIME': timedelta(days=30),
+    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
+    'ROTATE_REFRESH_TOKENS': False,
+    'BLACKLIST_AFTER_ROTATION': False,
+    'UPDATE_LAST_LOGIN': False,
+
+    'ALGORITHM': 'HS256',
+    'SIGNING_KEY': SECRET_KEY,
+    'VERIFYING_KEY': None,
+    'AUDIENCE': None,
+    'ISSUER': None,
+    'JWK_URL': None,
+    'LEEWAY': 0,
+
+    'AUTH_HEADER_TYPES': ('Bearer',),
+    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
+    'USER_ID_FIELD': '_id',
+    'USER_ID_CLAIM': 'user_id',
+    'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
+
+    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
+    'TOKEN_TYPE_CLAIM': 'token_type',
+    'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
+
+    'JTI_CLAIM': 'jti',
+
+    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
+    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
+    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
+}
+
+
+REST_FRAMEWORK = {
+    'DEFAULT_AUTHENTICATION_CLASSES': (
+        'rest_framework_simplejwt.authentication.JWTAuthentication',
+    )
+}
+
+

+ 123 - 0
store_back/settings.py

@@ -0,0 +1,123 @@
+"""
+Django settings for store_back project.
+
+Generated by 'django-admin startproject' using Django 4.0.4.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.0/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/4.0/ref/settings/
+"""
+
+from pathlib import Path
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'django-insecure-@&mo#&9)pe=y_r#4i+teev4_u*_4p-#$6(z9gdtzzt0vw6mdw9'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+]
+
+MIDDLEWARE = [
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'store_back.urls'
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'store_back.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': BASE_DIR / 'db.sqlite3',
+    }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/4.0/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/4.0/howto/static-files/
+
+STATIC_URL = 'static/'
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

+ 19 - 0
store_back/urls copy.py

@@ -0,0 +1,19 @@
+
+from django.contrib import admin
+from django.urls import path, include
+from django.conf.urls.static import static
+from django.conf import settings
+
+
+
+urlpatterns = [
+    path('api/', include('goods.urls')),
+    path('api/', include('orders.urls')),
+    path('api/', include('categories.urls')),
+    path('api/auth/',include('authAPI.urls')),
+    path('api/admin/', admin.site.urls),
+
+]
+
+
+urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

+ 21 - 0
store_back/urls.py

@@ -0,0 +1,21 @@
+"""store_back URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/4.0/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path
+
+urlpatterns = [
+    path('admin/', admin.site.urls),
+]

+ 16 - 0
store_back/wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for store_back project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'store_back.settings')
+
+application = get_wsgi_application()