linter, docker updated, minor byg fixed and shortener updates

This commit is contained in:
Alexander Karpov 2023-02-10 13:30:20 +03:00
parent 222138193b
commit 22db41f6f8
18 changed files with 150 additions and 151 deletions

View File

@ -21,7 +21,7 @@ repos:
- id: black
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
rev: 5.12.0
hooks:
- id: isort

View File

@ -0,0 +1,5 @@
from django.contrib import admin
from akarpov.shortener.models import Link
admin.site.register(Link)

View File

@ -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"]

View File

@ -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}"

10
akarpov/shortener/urls.py Normal file
View File

@ -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("<str:slug>", link_detail_view, name="view"),
]

View File

@ -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()

View File

@ -1,4 +1,4 @@
{% load static i18n %}<!DOCTYPE html>
{% load static i18n active_link_tags %}<!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %}
<html lang="{{ LANGUAGE_CODE }}">
<head>
@ -48,31 +48,25 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="{% url 'home' %}">Home <span class="visually-hidden">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'about' %}">About</a>
</li>
{% if request.user.is_authenticated %}
<li class="nav-item">
{# URL provided by django-allauth/account/urls.py #}
<a class="nav-link" href="{% url 'users:detail' request.user.username %}">{% translate "My Profile" %}</a>
<a class="nav-link {% active_link 'users:detail' %}" href="{% url 'users:detail' request.user.username %}">{% translate "My Profile" %}</a>
</li>
<li class="nav-item">
{# URL provided by django-allauth/account/urls.py #}
<a class="nav-link" href="{% url 'account_logout' %}">{% translate "Sign Out" %}</a>
<a class="nav-link {% active_link 'account_logout' %}" href="{% url 'account_logout' %}">{% if request.user.image_cropped %}<img class="rounded" width="20" src="{{ request.user.image_cropped.url }}" alt=""> {% endif %}{% translate "Sign Out" %}</a>
</li>
{% else %}
{% if ACCOUNT_ALLOW_REGISTRATION %}
<li class="nav-item">
{# URL provided by django-allauth/account/urls.py #}
<a id="sign-up-link" class="nav-link" href="{% url 'account_signup' %}">{% translate "Sign Up" %}</a>
<a id="sign-up-link" class="nav-link {% active_link 'account_signup' %}" href="{% url 'account_signup' %}">{% translate "Sign Up" %}</a>
</li>
{% endif %}
<li class="nav-item">
{# URL provided by django-allauth/account/urls.py #}
<a id="log-in-link" class="nav-link" href="{% url 'account_login' %}">{% translate "Sign In" %}</a>
<a id="log-in-link" class="nav-link {% active_link 'account_login' %}" href="{% url 'account_login' %}">{% translate "Sign In" %}</a>
</li>
{% endif %}
</ul>
@ -81,9 +75,7 @@
</nav>
</div>
<div class="container">
{% if messages %}
{% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}">
@ -94,21 +86,12 @@
{% endif %}
{% block content %}
<p>Use this document as a way to quick start any new project.</p>
{% endblock content %}
</div> <!-- /container -->
</div>
{% 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:
<script>
window.addEventListener('DOMContentLoaded', () => {/* Run whatever you want */});
</script>
{% endcomment %}
{% endblock inline_javascript %}
</body>
</html>

View File

@ -40,32 +40,31 @@
<p>{{ post.body|safe }}</p>
<div class="mt-4">
<hr>
<div class="row g-2">
<div class="col-md-auto" id="rating">
{% if request.user.is_authenticated %}
{% autoescape off %} {{ rating_bar }} {% endautoescape %}
{% else %}
{% if post.rating < 0 %}
<div class="success col-auto align-self-center mt-1"> {{ post.rating }}</div>
{% elif post.rating == 0 %}
<div class="success col-auto align-self-center gray fw-light mt-1"> {{ post.rating }}</div>
<div class="row g-2 d-flex">
<div class="col-md-auto align-items-center justify-content-center row">
<div id="rating" class="col-auto">
{% if request.user.is_authenticated %}
{% autoescape off %} {{ rating_bar }} {% endautoescape %}
{% else %}
<div class="success col-auto align-self-center mt-1"> +{{ post.rating }}</div>
{% if post.rating < 0 %}
<div class="col-auto align-self-center mt-1"> {{ post.rating }}</div>
{% elif post.rating == 0 %}
<div class="col-auto align-self-center gray fw-light mt-1"> {{ post.rating }}</div>
{% else %}
<div class="col-auto align-self-center mt-1"> +{{ post.rating }}</div>
{% endif %}
{% endif %}
{% endif %}
</div>
<div class="justify-content-center text-center col-auto">
<i class="bi bi-eye"></i> <div class="ms-1">{{ post.post_views | intword }}</div>
</div>
<div class="col-md-auto mt-2 d-flex justify-content-center text-center col-sm-2">
<i class="bi bi-eye align-self-center"></i> <div class="align-self-center ms-1">{{ post.post_views | intword }}</div>
<div class="justify-content-center text-center col-auto align-items-center justify-content-center">
<i class="bi bi-chat"></i> <div class="ms-1"> {{ post.comment_count }}</div>
</div>
<div class="col-md-auto mt-2 d-flex justify-content-center text-center col-sm-2">
<i class="bi bi-chat align-self-center"></i> <div class="align-self-center ms-1"> {{ post.comment_count }}</div>
</div>
<div class="col-6 col-sm-2 col-xl-6"></div>
<div class="col-md-auto mt-3 col-sm-2 d-flex justify-content-center text-center">
Created: {{ post.created|date:"d.m.Y" }} {{ post.created|time:"H:i" }}
</div>
<div class="col-md-auto mt-3 d-flex justify-content-center text-center">
Updated: {{ post.edited|date:"d.m.Y" }} {{ post.edited|time:"H:i" }}
<div class="col-md-auto align-items-center justify-content-center row ms-md-auto text-center">
<p class="col-auto">Created: {{ post.created|date:"d.m.Y" }} {{ post.created|time:"H:i" }}</p>
<p class="col-auto">Updated: {{ post.edited|date:"d.m.Y" }} {{ post.edited|time:"H:i" }}</p>
</div>
</div>
</div>

View File

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<form class="form-horizontal" enctype="multipart/form-data" method="post">
{% csrf_token %}
{{ form|crispy }}
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-success">Create</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,6 @@
{% extends "base.html" %}
{% block content %}
{{ link }}
{% endblock %}

View File

@ -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

View File

@ -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

View File

@ -1,7 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
make livehtml

View File

@ -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"

View File

@ -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")),

View File

@ -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

16
poetry.lock generated
View File

@ -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"

View File

@ -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]