Browse Source

+ goods graphQL

ilya_shyian 2 years ago
parent
commit
4671986d04

+ 4 - 2
store_back/apps/authAPI/serializers.py

@@ -1,5 +1,7 @@
 from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
-import datetime
+from datetime import datetime
+
+
 class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
 
     @classmethod
@@ -7,7 +9,7 @@ class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
         token = super().get_token(user)
 
         # Add custom claims
-        token['iat'] = datetime.datetime.now()
+        token['iat'] = str(datetime.timestamp(datetime.now()))
         token["sub"] = {
             "acl":["anon"],
         }

+ 33 - 0
store_back/apps/goods/migrations/0004_alter_good_amount_alter_good_description_and_more.py

@@ -0,0 +1,33 @@
+# Generated by Django 4.0.4 on 2022-06-23 17:46
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('goods', '0003_good_date'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='good',
+            name='amount',
+            field=models.IntegerField(blank=True, default=0, verbose_name='amount'),
+        ),
+        migrations.AlterField(
+            model_name='good',
+            name='description',
+            field=models.CharField(blank=True, default='', max_length=1000, verbose_name='description'),
+        ),
+        migrations.AlterField(
+            model_name='good',
+            name='name',
+            field=models.CharField(blank=True, default='', max_length=200, verbose_name='name'),
+        ),
+        migrations.AlterField(
+            model_name='good',
+            name='price',
+            field=models.IntegerField(blank=True, default=0, verbose_name='price'),
+        ),
+    ]

+ 4 - 4
store_back/apps/goods/models.py

@@ -13,10 +13,10 @@ class Image(models.Model):
 
 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)
+    name = models.CharField('name',default="", max_length = 200,blank=True)
+    description = models.CharField('description',default="", max_length = 1000,blank=True)
+    price = models.IntegerField("price", default=0,blank=True)
+    amount = models.IntegerField("amount", default=0,blank=True)
     images = models.ManyToManyField(Image,related_name ="goods", blank = True)
     date = models.DateTimeField(default=timezone.now)
 

+ 226 - 0
store_back/apps/goods/schema.py

@@ -0,0 +1,226 @@
+import graphene
+from graphene_django.types import DjangoObjectType
+from graphql_jwt.decorators import login_required
+from .models import Good,Image
+import json
+from functools import reduce
+from .serializers import GoodSerializer
+import operator
+from django.db.models import Q
+
+
+class ImageType(DjangoObjectType):
+    _id = graphene.String(name='_id')
+    class Meta:
+        model = Image
+        exclude_fields = ('_id',)
+
+    def resolve__id(self,info):
+        return self._id
+
+class ImageInput(graphene.InputObjectType):
+    _id = graphene.String(name='_id')
+    url = graphene.String(name='url',required=True)
+
+
+class GoodType(DjangoObjectType):
+    _id = graphene.String(name='_id')
+    images = graphene.List(ImageType)
+    name = graphene.String()
+    description = graphene.String()
+    price = graphene.Int()
+    amount = graphene.Int()
+
+    class Meta:
+        model = Good
+        exclude_fields = ('_id',"name","description","price","amount",)
+
+    def resolve__id(self,info):
+        return self._id
+
+    def resolve_images(self,info):
+        return self.images.all()
+
+    def resolve_name(self,info):
+        return self.name
+
+    def resolve_description(self,info):
+        return self.description
+
+    def resolve_price(self,info):
+        return self.price
+
+    def resolve_amount(self,info):
+        return self.amount
+
+
+class GoodInput(graphene.InputObjectType):
+    _id = graphene.String(name='_id')
+    images = graphene.List(ImageInput)
+    name = graphene.String()
+    description = graphene.String()
+    price = graphene.Int()
+    amount = graphene.Int()
+
+
+
+
+
+class Query(graphene.ObjectType):
+    GoodFind = graphene.List(GoodType,query = graphene.String())
+    GoodFindOne = graphene.Field(GoodType,query = graphene.String())
+
+    ImageFind = graphene.List(ImageType,query = graphene.String())
+    ImageFindOne = graphene.Field(ImageType,query = graphene.String())
+
+    def resolve_GoodFind(self,info,query = "[{}]"):
+        additional_params = {}
+        query_list = json.loads(query)
+        filter_params = query_list[0]
+        if len(query_list) > 1:
+            additional_params = query_list[1]
+
+        skip = additional_params.get("skip",0)
+        limit = additional_params.get("limit",20)
+        order_by = additional_params.get("orderBy","_id")
+
+        query_set = Good.objects.all()
+
+
+        if len(filter_params):
+            query_set = query_set.filter(reduce(operator.and_,(Q(**d) for d in [dict([i]) for i in filter_params.items()])))
+
+
+        return query_set
+
+
+    def resolve_GoodFindOne(self,info,query = "[{}]"):
+        additional_params = {}
+        query_list = json.loads(query)
+        filter_params = query_list[0]
+        if len(query_list) > 1:
+            additional_params = query_list[1]
+
+        skip = additional_params.get("skip",0)
+        limit = additional_params.get("limit",20)
+        order_by = additional_params.get("orderBy","_id")
+
+        query_set = Good.objects.all()
+
+        if len(filter_params):
+            query_set = query_set.filter(reduce(operator.and_,(Q(**d) for d in [dict([i]) for i in filter_params.items()])))
+
+        return query_set.first()
+
+
+
+    def resolve_ImageFind(self,info,query = "[{}]"):
+        additional_params = {}
+        query_list = json.loads(query)
+        filter_params = query_list[0]
+        if len(query_list) > 1:
+            additional_params = query_list[1]
+
+        skip = additional_params.get("skip",0)
+        limit = additional_params.get("limit",20)
+        order_by = additional_params.get("orderBy","_id")
+
+        query_set = Image.objects.all()
+
+        if len(filter_params):
+            query_set = query_set.filter(reduce(operator.and_,(Q(**d) for d in [dict([i]) for i in filter_params.items()])))
+
+
+        return query_set
+
+
+    def resolve_ImageFindOne(self,info,query = "[{}]"):
+        additional_params = {}
+        query_list = json.loads(query)
+        filter_params = query_list[0]
+        if len(query_list) > 1:
+            additional_params = query_list[1]
+
+        skip = additional_params.get("skip",0)
+        limit = additional_params.get("limit",20)
+        order_by = additional_params.get("orderBy","_id")
+
+        query_set = Image.objects.all()
+
+        if len(filter_params):
+            query_set = query_set.filter(reduce(operator.and_,(Q(**d) for d in [dict([i]) for i in filter_params.items()])))
+
+        return query_set.first()
+
+
+
+
+class GoodUpsert(graphene.Mutation):
+
+    class Arguments:
+        good = GoodInput(required=True)
+
+    Output =GoodType
+
+    @staticmethod
+    def mutate(root,info,good):
+        # user = info.context.user
+        # if not user.is_superuser:
+        #     raise Exception("Authentication credentials were not provided")
+
+
+        new_good={}
+        try:
+            _id = good._id
+            new_good = Good.objects.get(_id = _id)
+            good.pop("_id",None)
+            new_good.__dict__.update(**good)
+            new_good.save()
+        except Exception as e:
+            new_good = Good(**good)
+            new_good.save()
+            print(GoodSerializer(new_good).data)
+        return GoodType(**GoodSerializer(new_good).data)
+
+
+
+
+class GoodDelete(graphene.Mutation):
+
+    class Arguments:
+        good = GoodInput(required=True)
+
+    Output =GoodType
+
+    @staticmethod
+    def mutate(root,info,good):
+        # user = info.context.user
+        # if not user.is_superuser:
+        #     raise Exception("Authentication credentials were not provided")
+
+
+        try:
+            _id = good._id
+            good_to_delete = Good.objects.get(_id=_id)
+            good_data = GoodSerializer(good_to_delete).data
+            good_to_delete.delete()
+        except:
+            raise Exception("Не вірні дані")
+
+
+
+        return GoodType(**good_data)
+
+
+
+
+
+
+
+class Mutations(graphene.ObjectType):
+
+    GoodUpsert = GoodUpsert.Field()
+    GoodDelete = GoodDelete.Field()
+
+
+

+ 17 - 0
store_back/schema.py

@@ -0,0 +1,17 @@
+import graphene
+from goods.schema import Query as good_query
+from goods.schema import Mutations as good_mutations
+
+import graphql_jwt
+
+
+class Mutation(good_mutations):
+    token_auth = graphql_jwt.ObtainJSONWebToken.Field()
+    verify_token = graphql_jwt.Verify.Field()
+
+
+class Query(good_query):
+    pass
+
+
+schema = graphene.Schema(query = Query,mutation=Mutation)

+ 30 - 1
store_back/settings.py

@@ -2,6 +2,10 @@
 
 import os,sys
 from datetime import timedelta
+import django
+
+from django.utils.encoding import force_str
+django.utils.encoding.force_text = force_str
 
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -41,6 +45,7 @@ INSTALLED_APPS = [
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'rest_framework',
+    'graphene_django',
     'goods.apps.GoodsConfig',
     'authAPI.apps.AuthAPIConfig',
     'orders.apps.OrdersConfig',
@@ -57,6 +62,14 @@ MIDDLEWARE = [
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 ]
 
+AUTHENTICATION_BACKENDS = [
+    "graphql_jwt.backends.JSONWebTokenBackend",
+    "django.contrib.auth.backends.ModelBackend",
+]
+
+
+
+
 ROOT_URLCONF = 'store_back.urls'
 
 TEMPLATES = [
@@ -135,6 +148,23 @@ MEDIA_URL = 'api/media/'
 
 DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
 
+GRAPHENE = {
+    'SCHEMA': 'store_back.schema',
+    "MIDDLEWARE": [
+        "graphql_jwt.middleware.JSONWebTokenMiddleware",
+    ],
+}
+
+GRAPHQL_JWT = {
+    'JWT_PAYLOAD_HANDLER': 'store_back.utils.jwt_payload',
+    'JWT_AUTH_HEADER_PREFIX': 'Bearer',
+    'JWT_VERIFY_EXPIRATION': True,
+    'JWT_LONG_RUNNING_REFRESH_TOKEN': True,
+    'JWT_EXPIRATION_DELTA': timedelta(days=30),
+    'JWT_REFRESH_EXPIRATION_DELTA':timedelta(days=1),
+    'JWT_SECRET_KEY': SECRET_KEY,
+    'JWT_ALGORITHM': 'HS256',
+}
 
 
 SIMPLE_JWT = {
@@ -143,7 +173,6 @@ SIMPLE_JWT = {
     'ROTATE_REFRESH_TOKENS': False,
     'BLACKLIST_AFTER_ROTATION': False,
     'UPDATE_LAST_LOGIN': False,
-
     'ALGORITHM': 'HS256',
     'SIGNING_KEY': SECRET_KEY,
     'VERIFYING_KEY': None,

+ 0 - 19
store_back/urls copy.py

@@ -1,19 +0,0 @@
-
-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)

+ 7 - 0
store_back/urls.py

@@ -1,8 +1,11 @@
 
 from django.contrib import admin
 from django.urls import path, include
+from graphene_django.views import GraphQLView
+from django.views.decorators.csrf import csrf_exempt
 from django.conf.urls.static import static
 from django.conf import settings
+from .schema import schema
 
 
 
@@ -12,6 +15,10 @@ urlpatterns = [
     path('api/', include('categories.urls')),
     path('api/auth/',include('authAPI.urls')),
     path('api/admin/', admin.site.urls),
+    path('graphql/',csrf_exempt(GraphQLView.as_view(
+        graphiql=True,
+        schema = schema
+    )))
 
 ]
 

+ 23 - 0
store_back/utils.py

@@ -0,0 +1,23 @@
+from datetime import datetime
+from graphql_jwt.settings import jwt_settings
+from store_back.settings import GRAPHQL_JWT
+
+## JWT payload for Hasura
+def jwt_payload(user, context=None):
+    token = {}
+    jwt_datetime = datetime.utcnow() + jwt_settings.JWT_EXPIRATION_DELTA
+    jwt_expires = int(jwt_datetime.timestamp())
+    token['username'] = str(user.username) # For library compatibility
+    token['exp'] = jwt_expires
+
+    token['iat'] = datetime.timestamp(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