diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3c9126e..ce801e2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,7 +27,7 @@ jobs: run: mypy . test: runs-on: ubuntu-latest - needs: [lint, types] + needs: [ lint, types ] container: python:3.12.2-slim services: postgres: @@ -43,6 +43,10 @@ jobs: --health-retries 5 ports: - 5432:5432 + redis: + image: redis:7.2.5-alpine + ports: + - 6379:6379 steps: - name: Checkout @@ -66,6 +70,8 @@ jobs: DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }} DATABASE_HOST: postgres DATABASE_PORT: 5432 + REDIS_HOST: ${{ secrets.REDIS_HOST }} + REDIS_PORT: ${{ secrets.REDIS_PORT }} DEBUG: ${{ secrets.DEBUG }} CORS_ALLOWED_ORIGINS: ${{ secrets.CORS_ALLOWED_ORIGINS }} ALLOWED_HOSTS: ${{ secrets.ALLOWED_HOSTS }} @@ -81,53 +87,55 @@ jobs: runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - - uses: actions/checkout@v2 - - name: Copy repository contents via scp - uses: appleboy/scp-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - port: ${{ secrets.PORT }} - key: ${{ secrets.SSHKEY }} - source: "." - target: "/var/www/mywebsite" - - name: Create .env file on remote server - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - port: ${{ secrets.PORT }} - key: ${{ secrets.SSHKEY }} - script: | - cd /var/www/mywebsite - sudo rm -f .env - sudo touch .env - sudo chmod 666 .env - sudo cat < .env - DEBUG=${{ secrets.DEBUG }} - CORS_ORIGIN_ALLOW_ALL=${{ secrets.CORS_ORIGIN_ALLOW_ALL }} - CORS_ALLOW_CREDENTIALS=${{ secrets.CORS_ALLOW_CREDENTIALS }} - CORS_ALLOWED_ORIGINS=${{ secrets.CORS_ALLOWED_ORIGINS }} - ALLOWED_HOSTS=${{ secrets.ALLOWED_HOSTS }} - DATABASE_NAME=${{ secrets.DATABASE_NAME }} - DATABASE_USER=${{ secrets.DATABASE_USER }} - DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }} - DATABASE_HOST=${{ secrets.DATABASE_HOST }} - DATABASE_PORT=${{ secrets.DATABASE_PORT }} - SECRET_KEY=${{ secrets.SECRET_KEY }} - EMAIL_HOST=${{ secrets.EMAIL_HOST }} - EMAIL_PORT=${{ secrets.EMAIL_PORT }} - EMAIL_USE_SSL=${{ secrets.EMAIL_USE_SSL }} - EMAIL_HOST_USER=${{ secrets.EMAIL_HOST_USER }} - EMAIL_HOST_PASSWORD=${{ secrets.EMAIL_HOST_PASSWORD }} - EOF - - name: Executing remote command - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - port: ${{ secrets.PORT }} - key: ${{ secrets.SSHKEY }} - script: | - cd /var/www/mywebsite - docker-compose up -d --build + - uses: actions/checkout@v2 + - name: Copy repository contents via scp + uses: appleboy/scp-action@master + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + port: ${{ secrets.PORT }} + key: ${{ secrets.SSHKEY }} + source: "." + target: "/var/www/mywebsite" + - name: Create .env file on remote server + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + port: ${{ secrets.PORT }} + key: ${{ secrets.SSHKEY }} + script: | + cd /var/www/mywebsite + sudo rm -f .env + sudo touch .env + sudo chmod 666 .env + sudo cat < .env + DEBUG=${{ secrets.DEBUG }} + CORS_ORIGIN_ALLOW_ALL=${{ secrets.CORS_ORIGIN_ALLOW_ALL }} + CORS_ALLOW_CREDENTIALS=${{ secrets.CORS_ALLOW_CREDENTIALS }} + CORS_ALLOWED_ORIGINS=${{ secrets.CORS_ALLOWED_ORIGINS }} + ALLOWED_HOSTS=${{ secrets.ALLOWED_HOSTS }} + DATABASE_NAME=${{ secrets.DATABASE_NAME }} + DATABASE_USER=${{ secrets.DATABASE_USER }} + DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }} + DATABASE_HOST=${{ secrets.DATABASE_HOST }} + DATABASE_PORT=${{ secrets.DATABASE_PORT }} + REDIS_HOST: ${{ secrets.REDIS_HOST }} + REDIS_PORT: ${{ secrets.REDIS_PORT }} + SECRET_KEY=${{ secrets.SECRET_KEY }} + EMAIL_HOST=${{ secrets.EMAIL_HOST }} + EMAIL_PORT=${{ secrets.EMAIL_PORT }} + EMAIL_USE_SSL=${{ secrets.EMAIL_USE_SSL }} + EMAIL_HOST_USER=${{ secrets.EMAIL_HOST_USER }} + EMAIL_HOST_PASSWORD=${{ secrets.EMAIL_HOST_PASSWORD }} + EOF + - name: Executing remote command + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + port: ${{ secrets.PORT }} + key: ${{ secrets.SSHKEY }} + script: | + cd /var/www/mywebsite + docker-compose up -d --build diff --git a/clients/views.py b/clients/views.py index 52ea698..fe9c13d 100644 --- a/clients/views.py +++ b/clients/views.py @@ -1,3 +1,4 @@ +from django.core.cache import cache from rest_framework import generics from rest_framework.permissions import IsAuthenticated @@ -12,6 +13,15 @@ class ClientAPIView(generics.ListCreateAPIView[Client]): serializer_class = ClientSerializer permission_classes = (IsAuthenticated,) + def get_queryset(self): + cached_clients = cache.get("clients_list") + if cached_clients: + return cached_clients + else: + clients = super().get_queryset() + cache.set("clients_list", clients, 60 * 15) + return clients + # Изменение данных записи клиента class ClientAPIUpdateView(generics.RetrieveUpdateAPIView[Client]): diff --git a/docker-compose.yml b/docker-compose.yml index 825362b..d02bd7e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: networks: - melnichanka healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DATABASE_USER} -d ${DATABASE_NAME}"] + test: [ "CMD-SHELL", "pg_isready -U ${DATABASE_USER} -d ${DATABASE_NAME}" ] interval: 10s timeout: 1s retries: 5 @@ -48,6 +48,14 @@ services: db: condition: service_healthy + redis: + image: redis:7.2.5-alpine + hostname: redis + ports: + - "6379:6379" + networks: + - melnichanka + networks: melnichanka: diff --git a/goods/views.py b/goods/views.py index 09087cd..9e55029 100644 --- a/goods/views.py +++ b/goods/views.py @@ -1,3 +1,4 @@ +from django.core.cache import cache from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated @@ -9,3 +10,12 @@ class GoodsViewSet(viewsets.ModelViewSet[Product]): queryset = Product.objects.all() serializer_class = GoodsSerializer permission_classes = (IsAuthenticated,) + + def get_queryset(self): + cached_goods = cache.get("goods_list") + if cached_goods: + return cached_goods + else: + goods = super().get_queryset() + cache.set("goods_list", goods, 60 * 15) + return goods diff --git a/melnichanka/settings.py b/melnichanka/settings.py index b6a7a79..10db991 100644 --- a/melnichanka/settings.py +++ b/melnichanka/settings.py @@ -21,7 +21,6 @@ # 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.2/howto/deployment/checklist/ @@ -31,7 +30,6 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = bool(os.getenv("DEBUG", "False")) - # CORS CORS_ORIGIN_ALLOW_ALL = bool(os.getenv("CORS_ORIGIN_ALLOW_ALL")) CORS_ALLOW_CREDENTIALS = bool(os.getenv("CORS_ALLOW_CREDENTIALS")) @@ -42,6 +40,10 @@ ALLOWED_HOSTS_RAW = os.getenv("ALLOWED_HOSTS") ALLOWED_HOSTS = ALLOWED_HOSTS_RAW.split(",") if ALLOWED_HOSTS_RAW else [] +# DebugToolBar +if DEBUG: + INTERNAL_IPS = ["127.0.0.1"] + # Application definition INSTALLED_APPS = [ @@ -79,7 +81,6 @@ "debug_toolbar.middleware.DebugToolbarMiddleware", ] - ROOT_URLCONF = "melnichanka.urls" TEMPLATES = [ @@ -100,7 +101,6 @@ WSGI_APPLICATION = "melnichanka.wsgi.application" - # Database # https://docs.djangoproject.com/en/4.2/ref/settings/#databases @@ -115,6 +115,23 @@ }, } +# Redis + +REDIS_HOST = os.getenv("REDIS_HOST") +REDIS_PORT = os.getenv("REDIS_PORT") + +# Cache + +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": f"redis://{REDIS_HOST}:{REDIS_PORT}/1", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + }, + } +} + # Password validation # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators @@ -133,7 +150,6 @@ }, ] - # Internationalization # https://docs.djangoproject.com/en/4.2/topics/i18n/ @@ -145,7 +161,6 @@ USE_TZ = True - # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.2/howto/static-files/ @@ -178,7 +193,6 @@ "BLACKLIST_AFTER_ROTATION": True, } - EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST = os.getenv("EMAIL_HOST") EMAIL_PORT_RAW = os.getenv("EMAIL_PORT") diff --git a/requirements.txt b/requirements.txt index 74aac15..807b87c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,7 @@ django-cors-headers==4.3.1 django-debug-toolbar==4.2.0 django-extensions==3.2.3 django-phonenumber-field==7.3.0 +django-redis==5.4.0 django-rest-passwordreset==1.4.0 django-stubs==4.2.7 django-stubs-ext==4.2.7 @@ -65,6 +66,7 @@ python-dateutil==2.9.0.post0 python-dotenv==1.0.0 pytz==2024.1 PyYAML==6.0.1 +redis==5.0.4 referencing==0.33.0 requests==2.31.0 rest-framework-simplejwt==0.0.2