mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-25 08:13:44 +03:00
added user badge tag, link info lookup
This commit is contained in:
parent
e2dd282bd9
commit
87d323ab2d
|
@ -42,7 +42,7 @@ def post_rating(sender, instance: PostRating, **kwargs):
|
|||
@receiver(pre_save, sender=Post)
|
||||
def post_update(sender, instance: Post, **kwargs):
|
||||
if instance.id:
|
||||
if "update_fields" in kwargs:
|
||||
if "update_fields" in kwargs and kwargs["update_fields"]:
|
||||
for field in kwargs["update_fields"]:
|
||||
clear_model_cache(instance, field)
|
||||
else:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{% extends "base.html" %}
|
||||
{% load users_extras %}
|
||||
{% load humanize %}
|
||||
{% load static %}
|
||||
|
||||
|
@ -14,9 +15,7 @@
|
|||
</h1>
|
||||
<div class="row g-2 ms-1">
|
||||
<div class="col-md-auto">
|
||||
By: <a href="{% url 'users:detail' post.creator.username %}">
|
||||
{% if post.creator.image_cropped %}<img class="rounded" width="20" src="{{ post.creator.image_cropped.url }}" alt=""> {% endif %}
|
||||
{{ post.creator.username }}</a>
|
||||
By: {% user_badge post.creator %}
|
||||
</div>
|
||||
<div class="col-md-auto fw-light">
|
||||
Created {{ post.created | naturalday }},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load users_extras %}
|
||||
{% load static %}
|
||||
|
||||
{% block meta %}
|
||||
|
@ -35,9 +36,7 @@
|
|||
</h1>
|
||||
<div class="col-md-4 col-sm-6 col-xs-auto mb-5">
|
||||
{% if not has_perm %}
|
||||
<p>Uploaded by: <a href="{% url 'users:detail' file.user.username %}">
|
||||
{% if file.user.image_cropped %}<img class="rounded" width="20" src="{{ file.user.image_cropped.url }}" alt=""> {% endif %}
|
||||
{{ file.user.username }}</a></p>
|
||||
<p>Uploaded by: {% user_badge file.creator %}</p>
|
||||
{% endif %}
|
||||
<p class="mt-2">Last updated: {{ file.modified|date:"d.m.Y" }} {{ file.modified|time:"H:i" }}</p>
|
||||
<p>File size: {{ file.file_size | filesizeformat }}</p>
|
||||
|
|
18
akarpov/templates/tools/shortener/public_view.html
Normal file
18
akarpov/templates/tools/shortener/public_view.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load users_extras %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
<div class="m-2">
|
||||
<h4>Link to: <a class="fs-4" href="{{ link.source }}">{{ link.full_source }}</a></h4>
|
||||
<p>Issued by: {% user_badge link.creator %}</p>
|
||||
<p>{{ request.get_host }}{% url 'short_url' slug=link.slug %} <button class="btn" data-clipboard-text="{{ request.get_host }}{% url 'short_url' slug=link.slug %}">
|
||||
<i style="font-size: 0.8em" class="bi bi-clipboard ml-2"></i>
|
||||
</button></p>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/clipboard.min.js' %}"></script>
|
||||
<script>
|
||||
new ClipboardJS('.btn');
|
||||
</script>
|
||||
{% endblock %}
|
3
akarpov/templates/users/badge.html
Normal file
3
akarpov/templates/users/badge.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<a href="{% url 'users:detail' user.username %}">
|
||||
{% if user.image_cropped %}<img class="rounded" width="20" src="{{ user.image_cropped.url }}" alt=""> {% endif %}
|
||||
{{ user.username }}</a>
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
</header>
|
||||
|
||||
<!-- bit of a bio; who are you? -->
|
||||
<div class="profile-bio">
|
||||
|
||||
<p>
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
from django.urls import path
|
||||
|
||||
from akarpov.tools.shortener.views import link_detail_view, short_link_create_view
|
||||
from akarpov.tools.shortener.views import (
|
||||
link_detail_view,
|
||||
link_public_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"),
|
||||
path("p/<str:slug>", link_public_detail_view, name="public_view"),
|
||||
path("revoked", short_link_create_view, name="revoked"),
|
||||
]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404, HttpResponseNotFound, HttpResponseRedirect
|
||||
from django.urls import reverse
|
||||
from django.views.generic import CreateView, DetailView, ListView, TemplateView
|
||||
from ipware import get_client_ip
|
||||
|
||||
|
@ -52,6 +53,16 @@ def get_context_data(self, **kwargs):
|
|||
link_detail_view = LinkDetailView.as_view()
|
||||
|
||||
|
||||
class LinkPublicDetailView(DetailView):
|
||||
template_name = "tools/shortener/public_view.html"
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
return get_link_from_slug(self.kwargs["slug"])
|
||||
|
||||
|
||||
link_public_detail_view = LinkPublicDetailView.as_view()
|
||||
|
||||
|
||||
class LinkRevokedView(TemplateView):
|
||||
template_name = "tools/shortener/revoked.html"
|
||||
|
||||
|
@ -60,7 +71,14 @@ class LinkRevokedView(TemplateView):
|
|||
|
||||
|
||||
def redirect_view(request, slug):
|
||||
# TODO: move to faster framework, like FastAPI
|
||||
# TODO: move to faster framework, like FastAPI, save token to celery to get user_id
|
||||
# TODO: add meta proxy
|
||||
if "+" in slug:
|
||||
return HttpResponseRedirect(
|
||||
reverse(
|
||||
"tools:shortener:public_view", kwargs={"slug": slug.replace("+", "")}
|
||||
)
|
||||
)
|
||||
link, pk = get_cached_link_source(slug)
|
||||
if not link:
|
||||
return HttpResponseNotFound("such link doesn't exist or has been revoked")
|
||||
|
|
0
akarpov/users/templatetags/__init__.py
Normal file
0
akarpov/users/templatetags/__init__.py
Normal file
10
akarpov/users/templatetags/users_extras.py
Normal file
10
akarpov/users/templatetags/users_extras.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django import template
|
||||
|
||||
from akarpov.users.models import User
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.inclusion_tag("users/badge.html", name="user_badge")
|
||||
def user_badge(user: User):
|
||||
return {"user": user}
|
|
@ -6,7 +6,7 @@
|
|||
from akarpov.utils.consts import URL_BASE
|
||||
from akarpov.utils.nums import to_base
|
||||
|
||||
URL_CHARACTERS = string.ascii_letters + string.digits + ";,:@&+-_.!~*'()#"
|
||||
URL_CHARACTERS = string.ascii_letters + string.digits + ";,:@&-_.!~*'()#"
|
||||
|
||||
|
||||
class TokenGenerator(PasswordResetTokenGenerator):
|
||||
|
@ -21,16 +21,20 @@ def generate_charset(length: int) -> str:
|
|||
return "".join(random.choice(string.ascii_letters) for _ in range(length))
|
||||
|
||||
|
||||
url_list = list(URL_CHARACTERS)
|
||||
url_len = len(url_list)
|
||||
|
||||
|
||||
def get_str_uuid(pk: int) -> str:
|
||||
return to_base(pk, list(URL_CHARACTERS))
|
||||
return to_base(pk, url_list)
|
||||
|
||||
|
||||
def get_pk_from_uuid(slug: str) -> int:
|
||||
res = 0
|
||||
for i, el in enumerate(slug[::-1]):
|
||||
if el not in URL_BASE:
|
||||
raise ValueError
|
||||
res += URL_BASE[el] * 78**i
|
||||
return 0
|
||||
res += URL_BASE[el] * url_len**i
|
||||
return res
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user