From 6769b2f6de4d5477eecf396bfb3683f834749e4c Mon Sep 17 00:00:00 2001 From: Alexandr Karpov Date: Tue, 6 Dec 2022 12:03:58 +0300 Subject: [PATCH] updated production, fixed image crop --- akarpov/blog/signals.py | 4 +- akarpov/common/tasks.py | 2 +- akarpov/templates/pages/about.html | 4 ++ akarpov/templates/pages/home.html | 6 ++- akarpov/templates/users/user_detail.html | 2 +- akarpov/users/signals.py | 4 +- akarpov/utils/files.py | 48 +++++++++++++++++++++--- compose/production/django/Dockerfile | 2 - compose/production/django/start | 6 +++ config/settings/production.py | 12 +++++- config/urls.py | 5 ++- production.yml | 14 ------- 12 files changed, 77 insertions(+), 32 deletions(-) diff --git a/akarpov/blog/signals.py b/akarpov/blog/signals.py index 143da5c..f88d3b4 100644 --- a/akarpov/blog/signals.py +++ b/akarpov/blog/signals.py @@ -25,7 +25,7 @@ def post_on_save(sender, instance: Post, **kwargs): "app_label": "blog", "model_name": "Post", }, - countdown=10, + countdown=2, ) else: instance.image_cropped = None @@ -87,5 +87,5 @@ def post_on_create(sender, instance: Post, created, **kwargs): "app_label": "blog", "model_name": "Post", }, - countdown=10, + countdown=2, ) diff --git a/akarpov/common/tasks.py b/akarpov/common/tasks.py index b7dfa18..6149c16 100644 --- a/akarpov/common/tasks.py +++ b/akarpov/common/tasks.py @@ -11,7 +11,7 @@ def crop_model_image(pk: int, app_label: str, model_name: str): instance = model.objects.get(pk=pk) instance.image_cropped.save( instance.image.path.split(".")[0].split("/")[-1] + ".png", - File(crop_image(instance.image.path, cut_to=(250, 250))), + File(crop_image(instance.image.path, length=250)), save=False, ) instance.save(update_fields=["image_cropped"]) diff --git a/akarpov/templates/pages/about.html b/akarpov/templates/pages/about.html index 94d9808..3fa91f2 100644 --- a/akarpov/templates/pages/about.html +++ b/akarpov/templates/pages/about.html @@ -1 +1,5 @@ {% extends "base.html" %} + +{% block content %} +

this is me, and thats my website

+{% endblock %} diff --git a/akarpov/templates/pages/home.html b/akarpov/templates/pages/home.html index 94d9808..b469222 100644 --- a/akarpov/templates/pages/home.html +++ b/akarpov/templates/pages/home.html @@ -1 +1,5 @@ -{% extends "base.html" %} +{% extends 'base.html' %} + +{% block content %} +

This is my site %evil text%

+{% endblock %} diff --git a/akarpov/templates/users/user_detail.html b/akarpov/templates/users/user_detail.html index e7f5d5e..afc04a8 100644 --- a/akarpov/templates/users/user_detail.html +++ b/akarpov/templates/users/user_detail.html @@ -8,7 +8,7 @@
- {% if object.image_cropped %}{% endif %} + {% if object.image_cropped %}{% endif %} diff --git a/akarpov/users/signals.py b/akarpov/users/signals.py index 7b057cb..0fa5e76 100644 --- a/akarpov/users/signals.py +++ b/akarpov/users/signals.py @@ -21,7 +21,7 @@ def on_change(sender, instance: User, **kwargs): "app_label": "users", "model_name": "User", }, - countdown=10, + countdown=2, ) else: instance.image_cropped = None @@ -39,5 +39,5 @@ def post_on_create(sender, instance: User, created, **kwargs): "app_label": "users", "model_name": "User", }, - countdown=10, + countdown=2, ) diff --git a/akarpov/utils/files.py b/akarpov/utils/files.py index f26b340..c0c0212 100644 --- a/akarpov/utils/files.py +++ b/akarpov/utils/files.py @@ -5,17 +5,55 @@ from PIL import Image -def crop_image(image_path: str, cut_to=(500, 500)): +def crop_image(image_path: str, length: int = 500): """Makes image's thumbnail bt given parameters. By default, crops to 500x500""" - img = Image.open(image_path) + image = Image.open(image_path) blob = BytesIO() try: - img.thumbnail(cut_to, Image.ANTIALIAS) + if image.size[0] < image.size[1]: + # The image is in portrait mode. Height is bigger than width. + + # This makes the width fit the LENGTH in pixels while conserving the ration. + resized_image = image.resize( + (length, int(image.size[1] * (length / image.size[0]))) + ) + + # Amount of pixel to lose in total on the height of the image. + required_loss = resized_image.size[1] - length + + # Crop the height of the image so as to keep the center part. + resized_image = resized_image.crop( + box=( + 0, + int(required_loss / 2), + length, + int(resized_image.size[1] - required_loss / 2), + ) + ) + else: + # This image is in landscape mode or already squared. The width is bigger than the heihgt. + + # This makes the height fit the LENGTH in pixels while conserving the ration. + resized_image = image.resize( + (int(image.size[0] * (length / image.size[1])), length) + ) + + # Amount of pixel to lose in total on the width of the image. + required_loss = resized_image.size[0] - length + + # Crop the width of the image so as to keep 1080 pixels of the center part. + resized_image = resized_image.crop( + box=( + int(required_loss / 2), + 0, + int(resized_image.size[0] - required_loss / 2), + length, + ) + ) + resized_image.save(blob, "PNG") except OSError: print("Can't crop") - - img.save(blob, "PNG") return blob diff --git a/compose/production/django/Dockerfile b/compose/production/django/Dockerfile index 59378f2..fa6f2f4 100644 --- a/compose/production/django/Dockerfile +++ b/compose/production/django/Dockerfile @@ -59,12 +59,10 @@ COPY --from=python-build-stage /usr/src/app/wheels /wheels/ RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \ && rm -rf /wheels/ - COPY --chown=django:django ./compose/production/django/entrypoint /entrypoint RUN sed -i 's/\r$//g' /entrypoint RUN chmod +x /entrypoint - COPY --chown=django:django ./compose/production/django/start /start RUN sed -i 's/\r$//g' /start RUN chmod +x /start diff --git a/compose/production/django/start b/compose/production/django/start index 7b10be1..043b87b 100644 --- a/compose/production/django/start +++ b/compose/production/django/start @@ -4,7 +4,13 @@ set -o errexit set -o pipefail set -o nounset +mkdir /app/staticfiles/ +chmod -R +r /app/staticfiles/ + python /app/manage.py collectstatic --noinput +python /app/manage.py makemigrations +python /app/manage.py migrate auth +python /app/manage.py migrate /usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app diff --git a/config/settings/production.py b/config/settings/production.py index 823660c..ba98960 100644 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -7,7 +7,7 @@ from sentry_sdk.integrations.redis import RedisIntegration from .base import * # noqa -from .base import env +from .base import APPS_DIR, ROOT_DIR, env # GENERAL # ------------------------------------------------------------------------------ @@ -64,8 +64,16 @@ # STATIC # ------------------------ STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" +STATIC_ROOT = str(ROOT_DIR / "staticfiles") +# https://docs.djangoproject.com/en/dev/ref/settings/#static-url +STATIC_URL = "/static/" +# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS +STATICFILES_DIRS = [str(APPS_DIR / "static")] # MEDIA # ------------------------------------------------------------------------------ +MEDIA_ROOT = str(APPS_DIR / "media") +# https://docs.djangoproject.com/en/dev/ref/settings/#media-url +MEDIA_URL = "/media/" # EMAIL # ------------------------------------------------------------------------------ @@ -98,7 +106,7 @@ ANYMAIL = { "MAILGUN_API_KEY": env("MAILGUN_API_KEY"), "MAILGUN_SENDER_DOMAIN": env("MAILGUN_DOMAIN"), - "MAILGUN_API_URL": env("MAILGUN_API_URL", default="https://api.mailgun.net/v3"), + "MAILGUN_API_URL": "https://api.mailgun.net/v3", } diff --git a/config/urls.py b/config/urls.py index 25fe306..852ee38 100644 --- a/config/urls.py +++ b/config/urls.py @@ -11,7 +11,7 @@ ) urlpatterns = [ - path("", include("akarpov.blog.urls", namespace="blog")), + path("home", TemplateView.as_view(template_name="pages/home.html"), name="home"), path( "about/", TemplateView.as_view(template_name="pages/about.html"), name="about" ), @@ -22,6 +22,7 @@ path("users/", include("akarpov.users.urls", namespace="users")), path("ckeditor/", include("ckeditor_uploader.urls")), path("accounts/", include("allauth.urls")), + path("", include("akarpov.blog.urls", namespace="blog")), # Your stuff: custom urls includes go here ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) @@ -35,7 +36,7 @@ path( "api/docs/", SpectacularSwaggerView.as_view(url_name="api-schema"), - name="home", + name="swagger", ), path( "api/redoc/", diff --git a/production.yml b/production.yml index 63dc0c7..3dad763 100644 --- a/production.yml +++ b/production.yml @@ -31,20 +31,6 @@ services: env_file: - ./.envs/.production/.postgres - traefik: - build: - context: . - dockerfile: ./compose/production/traefik/Dockerfile - image: akarpov_production_traefik - depends_on: - - django - volumes: - - production_traefik:/etc/traefik/acme:z - ports: - - "0.0.0.0:80:80" - - "0.0.0.0:443:443" - - "0.0.0.0:5555:5555" - redis: image: redis:6