From 22db41f6f82a1e31599f1c4d8d182985cef41f59 Mon Sep 17 00:00:00 2001 From: Alexandr Karpov Date: Fri, 10 Feb 2023 13:30:20 +0300 Subject: [PATCH] linter, docker updated, minor byg fixed and shortener updates --- .pre-commit-config.yaml | 2 +- akarpov/shortener/admin.py | 5 +++ akarpov/shortener/forms.py | 17 +++++++ akarpov/shortener/models.py | 4 ++ akarpov/shortener/urls.py | 10 +++++ akarpov/shortener/views.py | 37 +++++++++++++++ akarpov/templates/base.html | 29 +++--------- akarpov/templates/blog/post.html | 41 +++++++++-------- akarpov/templates/shortener/create.html | 14 ++++++ akarpov/templates/shortener/view.html | 6 +++ compose/local/django/Dockerfile | 28 ++++-------- compose/local/docs/Dockerfile | 60 ------------------------- compose/local/docs/start | 7 --- config/settings/base.py | 6 +++ config/urls.py | 1 + local.yml | 17 ------- poetry.lock | 16 ++++++- pyproject.toml | 1 + 18 files changed, 150 insertions(+), 151 deletions(-) create mode 100644 akarpov/shortener/forms.py create mode 100644 akarpov/shortener/urls.py create mode 100644 akarpov/templates/shortener/create.html create mode 100644 akarpov/templates/shortener/view.html delete mode 100644 compose/local/docs/Dockerfile delete mode 100644 compose/local/docs/start diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 433d97d..54926ef 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: - id: black - repo: https://github.com/PyCQA/isort - rev: 5.10.1 + rev: 5.12.0 hooks: - id: isort diff --git a/akarpov/shortener/admin.py b/akarpov/shortener/admin.py index e69de29..1d82c4a 100644 --- a/akarpov/shortener/admin.py +++ b/akarpov/shortener/admin.py @@ -0,0 +1,5 @@ +from django.contrib import admin + +from akarpov.shortener.models import Link + +admin.site.register(Link) diff --git a/akarpov/shortener/forms.py b/akarpov/shortener/forms.py new file mode 100644 index 0000000..fdd0cba --- /dev/null +++ b/akarpov/shortener/forms.py @@ -0,0 +1,17 @@ +from django import forms +from django.core.validators import URLValidator + +from akarpov.shortener.models import Link + + +class LinkForm(forms.ModelForm): + source = forms.URLField( + max_length=500, + widget=forms.TextInput, + help_text="Please enter the url of the page", + validators=[URLValidator], + ) + + class Meta: + model = Link + fields = ["source"] diff --git a/akarpov/shortener/models.py b/akarpov/shortener/models.py index 2e59a3d..aed6414 100644 --- a/akarpov/shortener/models.py +++ b/akarpov/shortener/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.urls import reverse from model_utils.models import TimeStampedModel @@ -13,6 +14,9 @@ class Link(TimeStampedModel): viewed = models.IntegerField(default=0) + def get_absolute_url(self): + return reverse("shortener:view", kwargs={"slug": self.slug}) + def __str__(self): return f"link to {self.source}" diff --git a/akarpov/shortener/urls.py b/akarpov/shortener/urls.py new file mode 100644 index 0000000..9a35e22 --- /dev/null +++ b/akarpov/shortener/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from akarpov.shortener.views import link_detail_view, short_link_create_view + +app_name = "shortener" + +urlpatterns = [ + path("", short_link_create_view, name="create"), + path("", link_detail_view, name="view"), +] diff --git a/akarpov/shortener/views.py b/akarpov/shortener/views.py index e69de29..a76b173 100644 --- a/akarpov/shortener/views.py +++ b/akarpov/shortener/views.py @@ -0,0 +1,37 @@ +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied +from django.views.generic import CreateView, DetailView + +from akarpov.shortener.forms import LinkForm +from akarpov.shortener.models import Link +from akarpov.shortener.services import get_link_from_slug + + +class ShortLinkCreateView(CreateView): + model = Link + form_class = LinkForm + + template_name = "shortener/create.html" + + def form_valid(self, form): + if self.request.user.is_authenticated: + form.instance.creator = self.request.user + return super().form_valid(form) + + +short_link_create_view = ShortLinkCreateView.as_view() + + +class LinkDetailView(DetailView): + + template_name = "shortener/view.html" + + def get_object(self, *args, **kwargs): + link = get_link_from_slug(self.kwargs["slug"]) + if not link: + raise ObjectDoesNotExist + if link.creator and link.creator != self.request.user: + raise PermissionDenied + return link + + +link_detail_view = LinkDetailView.as_view() diff --git a/akarpov/templates/base.html b/akarpov/templates/base.html index fdca581..0a65734 100644 --- a/akarpov/templates/base.html +++ b/akarpov/templates/base.html @@ -1,4 +1,4 @@ -{% load static i18n %} +{% load static i18n active_link_tags %} {% get_current_language as LANGUAGE_CODE %} @@ -48,31 +48,25 @@ -
- {% if messages %} {% for message in messages %}
@@ -94,21 +86,12 @@ {% endif %} {% block content %} -

Use this document as a way to quick start any new project.

{% endblock content %} - -
+
{% block modal %}{% endblock modal %} {% block inline_javascript %} - {% comment %} - Script tags with only code, no src (defer by default). To run - with a "defer" so that you run inline code: - - {% endcomment %} {% endblock inline_javascript %} diff --git a/akarpov/templates/blog/post.html b/akarpov/templates/blog/post.html index dff8a1a..b85c1b9 100644 --- a/akarpov/templates/blog/post.html +++ b/akarpov/templates/blog/post.html @@ -40,32 +40,31 @@

{{ post.body|safe }}


-
-
- {% if request.user.is_authenticated %} - {% autoescape off %} {{ rating_bar }} {% endautoescape %} - {% else %} - {% if post.rating < 0 %} -
{{ post.rating }}
- {% elif post.rating == 0 %} -
{{ post.rating }}
+
+
+
+ {% if request.user.is_authenticated %} + {% autoescape off %} {{ rating_bar }} {% endautoescape %} {% else %} -
+{{ post.rating }}
+ {% if post.rating < 0 %} +
{{ post.rating }}
+ {% elif post.rating == 0 %} +
{{ post.rating }}
+ {% else %} +
+{{ post.rating }}
+ {% endif %} {% endif %} - {% endif %} +
+
+
{{ post.post_views | intword }}
-
-
{{ post.post_views | intword }}
+
+
{{ post.comment_count }}
-
-
{{ post.comment_count }}
-
-
- Created: {{ post.created|date:"d.m.Y" }} {{ post.created|time:"H:i" }} -
-
- Updated: {{ post.edited|date:"d.m.Y" }} {{ post.edited|time:"H:i" }} +
+

Created: {{ post.created|date:"d.m.Y" }} {{ post.created|time:"H:i" }}

+

Updated: {{ post.edited|date:"d.m.Y" }} {{ post.edited|time:"H:i" }}

diff --git a/akarpov/templates/shortener/create.html b/akarpov/templates/shortener/create.html new file mode 100644 index 0000000..0f4c960 --- /dev/null +++ b/akarpov/templates/shortener/create.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} +{% load crispy_forms_tags %} + +{% block content %} +
+ {% csrf_token %} + {{ form|crispy }} +
+
+ +
+
+
+{% endblock %} diff --git a/akarpov/templates/shortener/view.html b/akarpov/templates/shortener/view.html new file mode 100644 index 0000000..0494c7e --- /dev/null +++ b/akarpov/templates/shortener/view.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} + + +{% block content %} +{{ link }} +{% endblock %} diff --git a/compose/local/django/Dockerfile b/compose/local/django/Dockerfile index 3102c54..bee8473 100644 --- a/compose/local/django/Dockerfile +++ b/compose/local/django/Dockerfile @@ -8,13 +8,6 @@ FROM python as python-build-stage ARG BUILD_ENVIRONMENT=local -# Install apt packages -RUN apt-get update && apt-get install --no-install-recommends -y \ - # dependencies for building Python packages - build-essential \ - # psycopg2 dependencies - libpq-dev - # Python 'run' stage FROM python as python-run-stage @@ -29,23 +22,18 @@ ENV BUILD_ENV ${BUILD_ENVIRONMENT} WORKDIR ${APP_HOME} # Install required system dependencies -RUN apt-get update && apt-get install --no-install-recommends -y \ - # psycopg2 dependencies - libpq-dev \ - # Translations dependencies - gettext \ - # cleaning up unused files - && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ - && rm -rf /var/lib/apt/lists/* +RUN apt-get update && \ + apt-get install -y build-essential libpq-dev gettext libmagic-dev libjpeg-dev zlib1g-dev && \ + apt-get purge -y --auto-remove -o APT:AutoRemove:RecommendsImportant=false && \ + rm -rf /var/lib/apt/lists/* -RUN pip install poetry +RUN curl -sSL https://install.python-poetry.org | python3 - +ENV PATH="/root/.local/bin:$PATH" -# Configuring poetry RUN poetry config virtualenvs.create false -COPY pyproject.toml poetry.lock / -# Installing requirements -RUN poetry install +COPY ./pyproject.toml ./poetry.lock /app/ +RUN poetry install --no-root --only main COPY ./compose/production/django/entrypoint /entrypoint diff --git a/compose/local/docs/Dockerfile b/compose/local/docs/Dockerfile deleted file mode 100644 index 1279863..0000000 --- a/compose/local/docs/Dockerfile +++ /dev/null @@ -1,60 +0,0 @@ -ARG PYTHON_VERSION=3.11-slim - -# define an alias for the specfic python version used in this file. -FROM python:${PYTHON_VERSION} as python - - -# Python build stage -FROM python as python-build-stage - -ENV PYTHONDONTWRITEBYTECODE 1 - -RUN apt-get update && apt-get install --no-install-recommends -y \ - # dependencies for building Python packages - build-essential \ - # psycopg2 dependencies - libpq-dev \ - # cleaning up unused files - && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ - && rm -rf /var/lib/apt/lists/* - - -# Python 'run' stage -FROM python as python-run-stage - -ARG BUILD_ENVIRONMENT -ENV PYTHONUNBUFFERED 1 -ENV PYTHONDONTWRITEBYTECODE 1 - -RUN apt-get update && apt-get install --no-install-recommends -y \ - # To run the Makefile - make \ - # psycopg2 dependencies - libpq-dev \ - # Translations dependencies - gettext \ - # Uncomment below lines to enable Sphinx output to latex and pdf - # texlive-latex-recommended \ - # texlive-fonts-recommended \ - # texlive-latex-extra \ - # latexmk \ - # cleaning up unused files - && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ - && rm -rf /var/lib/apt/lists/* - - -RUN pip install poetry - -# Configuring poetry -RUN poetry config virtualenvs.create false -COPY pyproject.toml poetry.lock / - -# Installing requirements -RUN poetry install - - -COPY ./compose/local/docs/start /start-docs -RUN sed -i 's/\r$//g' /start-docs -RUN chmod +x /start-docs - -WORKDIR /docs diff --git a/compose/local/docs/start b/compose/local/docs/start deleted file mode 100644 index fd2e0de..0000000 --- a/compose/local/docs/start +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -set -o errexit -set -o pipefail -set -o nounset - -make livehtml diff --git a/config/settings/base.py b/config/settings/base.py index 834fbdd..b7f0f1f 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -110,6 +110,7 @@ "cacheops", "extra_settings", "drf_chunked_upload", + "active_link", # django-cms "cms", "menus", @@ -514,3 +515,8 @@ # ------------------------------------------------------------------------------ SHORTENER_ADD_SLUG = True SHORTENER_SLUG_LENGTH = 3 + + +# ACTIVE_LINK +# ------------------------------------------------------------------------------ +ACTIVE_LINK_CSS_CLASS = "active" diff --git a/config/urls.py b/config/urls.py index e4dc419..49ffc21 100644 --- a/config/urls.py +++ b/config/urls.py @@ -22,6 +22,7 @@ # User management path("users/", include("akarpov.users.urls", namespace="users")), path("tools/", include("akarpov.tools.urls", namespace="tools")), + path("shortener/", include("akarpov.shortener.urls", namespace="shortener")), path("ckeditor/", include("ckeditor_uploader.urls")), path("accounts/", include("allauth.urls")), path("", include("akarpov.blog.urls", namespace="blog")), diff --git a/local.yml b/local.yml index dd0c6c8..838c05b 100644 --- a/local.yml +++ b/local.yml @@ -37,23 +37,6 @@ services: env_file: - ./.envs/.local/.postgres - docs: - image: akarpov_local_docs - container_name: akarpov_local_docs - platform: linux/x86_64 - build: - context: . - dockerfile: ./compose/local/docs/Dockerfile - env_file: - - ./.envs/.local/.django - volumes: - - ./docs:/docs:z - - ./config:/app/config:z - - ./akarpov:/app/akarpov:z - ports: - - "9000:9000" - command: /start-docs - mailhog: image: mailhog/mailhog:v1.0.0 container_name: akarpov_local_mailhog diff --git a/poetry.lock b/poetry.lock index 9af4c4a..029c945 100644 --- a/poetry.lock +++ b/poetry.lock @@ -820,6 +820,18 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""} argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] +[[package]] +name = "django-active-link" +version = "0.1.8" +description = "The best way to highlight active links in your Django app." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "django-active-link-0.1.8.tar.gz", hash = "sha256:87aac58cc89913ff3b017b91cb24cda0dbb05945aa46c6a1428d0744b56a3e1f"}, + {file = "django_active_link-0.1.8-py2.py3-none-any.whl", hash = "sha256:a6a94f92e9150d05be4491e10e5dfb3274c08dd88866081f5f90ea2d738db647"}, +] + [[package]] name = "django-allauth" version = "0.51.0" @@ -2031,7 +2043,6 @@ category = "main" optional = false python-versions = "*" files = [ - {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, ] @@ -3648,6 +3659,7 @@ category = "main" optional = false python-versions = "*" files = [ + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, ] @@ -3762,4 +3774,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "63c03ff6211f20d9ad19aa9761aac2896a70345a441315ea44e09e8e0a370fcc" +content-hash = "69ccdf0950f670e050d0ee1985996ab9873538a9a39a72f58adeee63b3ada902" diff --git a/pyproject.toml b/pyproject.toml index 33c660d..8f79771 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,7 @@ django-sekizai = "^4.0.0" amzqr = "^0.0.1" django-chunked-upload = "^2.0.0" drf-chunked-upload = "^0.5.1" +django-active-link = "^0.1.8" [build-system]