mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2025-07-11 11:12:17 +03:00
added more common models, added short link base model, updated shortener
This commit is contained in:
parent
39ef0fb06b
commit
9b6934288c
24
akarpov/blog/migrations/0003_post_short_link.py
Normal file
24
akarpov/blog/migrations/0003_post_short_link.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-15 12:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shortener", "0001_initial"),
|
||||||
|
("blog", "0002_alter_comment_options"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="post",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
25
akarpov/blog/migrations/0004_alter_post_short_link.py
Normal file
25
akarpov/blog/migrations/0004_alter_post_short_link.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-15 12:39
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shortener", "0001_initial"),
|
||||||
|
("blog", "0003_post_short_link"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="post",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,15 +1,16 @@
|
||||||
from ckeditor_uploader.fields import RichTextUploadingField
|
from ckeditor_uploader.fields import RichTextUploadingField
|
||||||
from colorfield.fields import ColorField
|
from colorfield.fields import ColorField
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Count, ImageField, SlugField
|
from django.db.models import Count, SlugField
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from akarpov.common.models import BaseImageModel
|
||||||
|
from akarpov.tools.shortener.models import ShortLink
|
||||||
from akarpov.users.models import User
|
from akarpov.users.models import User
|
||||||
from akarpov.utils.files import user_file_upload_mixin
|
|
||||||
from akarpov.utils.string import cleanhtml
|
from akarpov.utils.string import cleanhtml
|
||||||
|
|
||||||
|
|
||||||
class Post(models.Model):
|
class Post(BaseImageModel, ShortLink):
|
||||||
title = models.CharField(max_length=100, blank=False)
|
title = models.CharField(max_length=100, blank=False)
|
||||||
body = RichTextUploadingField(blank=False)
|
body = RichTextUploadingField(blank=False)
|
||||||
|
|
||||||
|
@ -25,9 +26,6 @@ class Post(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
edited = models.DateTimeField(auto_now=True)
|
edited = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
image = ImageField(upload_to=user_file_upload_mixin, blank=True)
|
|
||||||
image_cropped = ImageField(upload_to="cropped/", blank=True)
|
|
||||||
|
|
||||||
tags = models.ManyToManyField("blog.Tag", related_name="posts")
|
tags = models.ManyToManyField("blog.Tag", related_name="posts")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from akarpov.utils.files import user_file_upload_mixin
|
||||||
|
|
||||||
|
|
||||||
|
class BaseImageModel(models.Model):
|
||||||
|
image = models.ImageField(upload_to=user_file_upload_mixin, blank=True)
|
||||||
|
image_cropped = models.ImageField(upload_to="cropped/", blank=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-15 12:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shortener", "0001_initial"),
|
||||||
|
("files", "0002_alter_basefile_options_alter_folder_options_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="basefile",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="folder",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-15 12:39
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shortener", "0001_initial"),
|
||||||
|
("files", "0003_basefile_short_link_folder_short_link"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="basefile",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="folder",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -7,12 +7,14 @@
|
||||||
SlugField,
|
SlugField,
|
||||||
TextField,
|
TextField,
|
||||||
)
|
)
|
||||||
|
from django.urls import reverse
|
||||||
from model_utils.models import TimeStampedModel
|
from model_utils.models import TimeStampedModel
|
||||||
|
|
||||||
|
from akarpov.tools.shortener.models import ShortLink
|
||||||
from akarpov.utils.files import user_file_upload_mixin
|
from akarpov.utils.files import user_file_upload_mixin
|
||||||
|
|
||||||
|
|
||||||
class BaseFile(TimeStampedModel):
|
class BaseFile(TimeStampedModel, ShortLink):
|
||||||
"""model to store user's files"""
|
"""model to store user's files"""
|
||||||
|
|
||||||
name = CharField(max_length=100)
|
name = CharField(max_length=100)
|
||||||
|
@ -28,16 +30,22 @@ class BaseFile(TimeStampedModel):
|
||||||
|
|
||||||
file = FileField(blank=False, upload_to=user_file_upload_mixin)
|
file = FileField(blank=False, upload_to=user_file_upload_mixin)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("files:view", kwargs={"slug": self.slug})
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"file: {self.name}"
|
return f"file: {self.name}"
|
||||||
|
|
||||||
|
|
||||||
class Folder(TimeStampedModel):
|
class Folder(TimeStampedModel, ShortLink):
|
||||||
name = CharField(max_length=100)
|
name = CharField(max_length=100)
|
||||||
slug = SlugField(max_length=20, blank=True)
|
slug = SlugField(max_length=20, blank=True)
|
||||||
|
|
||||||
user = ForeignKey("users.User", related_name="files_folders", on_delete=CASCADE)
|
user = ForeignKey("users.User", related_name="files_folders", on_delete=CASCADE)
|
||||||
parent = ForeignKey("self", related_name="children", on_delete=CASCADE)
|
parent = ForeignKey("self", related_name="children", on_delete=CASCADE)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("files:folder", kwargs={"slug": self.slug})
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"file: {self.name}"
|
return f"file: {self.name}"
|
||||||
|
|
9
akarpov/files/urls.py
Normal file
9
akarpov/files/urls.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from akarpov.files.views import files_view, folder_view
|
||||||
|
|
||||||
|
app_name = "files"
|
||||||
|
urlpatterns = [
|
||||||
|
path("<str:slug>", files_view, name="view"),
|
||||||
|
path("f/<str:slug>", folder_view, name="folder"),
|
||||||
|
]
|
|
@ -0,0 +1,21 @@
|
||||||
|
from django.views.generic import DetailView
|
||||||
|
|
||||||
|
from akarpov.files.models import BaseFile, Folder
|
||||||
|
|
||||||
|
|
||||||
|
class FileView(DetailView):
|
||||||
|
template_name = "files/view.html"
|
||||||
|
model = BaseFile
|
||||||
|
slug_field = "slug"
|
||||||
|
|
||||||
|
|
||||||
|
files_view = FileView.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
class FileFolderView(DetailView):
|
||||||
|
template_name = "files/folder.html"
|
||||||
|
model = Folder
|
||||||
|
slug_field = "slug"
|
||||||
|
|
||||||
|
|
||||||
|
folder_view = FileFolderView.as_view()
|
27
akarpov/test_platform/migrations/0006_form_short_link.py
Normal file
27
akarpov/test_platform/migrations/0006_form_short_link.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-15 12:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shortener", "0001_initial"),
|
||||||
|
(
|
||||||
|
"test_platform",
|
||||||
|
"0005_alter_basequestion_options_basequestion_order_and_more",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="form",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-15 12:39
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shortener", "0001_initial"),
|
||||||
|
("test_platform", "0006_form_short_link"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="form",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -7,12 +7,13 @@
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from polymorphic.models import PolymorphicModel
|
from polymorphic.models import PolymorphicModel
|
||||||
|
|
||||||
|
from akarpov.common.models import BaseImageModel
|
||||||
|
from akarpov.tools.shortener.models import ShortLink
|
||||||
from akarpov.users.models import User
|
from akarpov.users.models import User
|
||||||
from akarpov.utils.base import SubclassesMixin
|
from akarpov.utils.base import SubclassesMixin
|
||||||
from akarpov.utils.files import user_file_upload_mixin
|
|
||||||
|
|
||||||
|
|
||||||
class Form(models.Model):
|
class Form(BaseImageModel, ShortLink):
|
||||||
name = models.CharField(max_length=200, blank=False)
|
name = models.CharField(max_length=200, blank=False)
|
||||||
description = models.TextField(blank=True)
|
description = models.TextField(blank=True)
|
||||||
|
|
||||||
|
@ -25,9 +26,6 @@ class Form(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
updated = models.DateTimeField(auto_now=True)
|
updated = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
image = models.ImageField(upload_to=user_file_upload_mixin, blank=True)
|
|
||||||
image_cropped = models.ImageField(upload_to="cropped/", blank=True)
|
|
||||||
|
|
||||||
passed = models.IntegerField(default=0)
|
passed = models.IntegerField(default=0)
|
||||||
time_since = models.DateTimeField(null=True, blank=True)
|
time_since = models.DateTimeField(null=True, blank=True)
|
||||||
time_till = models.DateTimeField(null=True, blank=True)
|
time_till = models.DateTimeField(null=True, blank=True)
|
||||||
|
|
0
akarpov/test_platform/templates/files/folder.html
Normal file
0
akarpov/test_platform/templates/files/folder.html
Normal file
0
akarpov/test_platform/templates/files/view.html
Normal file
0
akarpov/test_platform/templates/files/view.html
Normal file
5
akarpov/test_platform/templates/shortener/revoked.html
Normal file
5
akarpov/test_platform/templates/shortener/revoked.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>This link has been revoked</h1>
|
||||||
|
{% endblock %}
|
|
@ -1,3 +1,5 @@
|
||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from model_utils.models import TimeStampedModel
|
from model_utils.models import TimeStampedModel
|
||||||
|
@ -31,3 +33,37 @@ class LinkViewMeta(models.Model):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"view on {self.link.source}"
|
return f"view on {self.link.source}"
|
||||||
|
|
||||||
|
|
||||||
|
def create_model_link(sender, instance, created, **kwargs):
|
||||||
|
# had to move to models due to circular import
|
||||||
|
if created:
|
||||||
|
link = Link.objects.create(
|
||||||
|
source=instance.get_absolute_url(), creator=instance.creator
|
||||||
|
)
|
||||||
|
instance.short_link = link
|
||||||
|
instance.save()
|
||||||
|
|
||||||
|
|
||||||
|
class ShortLink(models.Model):
|
||||||
|
short_link: Link | None = models.ForeignKey(
|
||||||
|
"shortener.Link", blank=True, null=True, on_delete=models.SET_NULL
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __init_subclass__(cls, **kwargs):
|
||||||
|
super().__init_subclass__(**kwargs)
|
||||||
|
models.signals.post_save.connect(create_model_link, sender=cls)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_absolute_url(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def get_short_link(self) -> str:
|
||||||
|
if self.short_link:
|
||||||
|
return reverse("short_url", kwargs={"slug": self.short_link.slug})
|
||||||
|
return reverse("tools:shortener:revoked")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from akarpov.tools.shortener.models import Link
|
from akarpov.tools.shortener.signals import Link
|
||||||
from akarpov.utils.generators import generate_charset, get_pk_from_uuid, get_str_uuid
|
from akarpov.utils.generators import get_pk_from_uuid
|
||||||
|
|
||||||
length = settings.SHORTENER_SLUG_LENGTH
|
length = settings.SHORTENER_SLUG_LENGTH
|
||||||
|
|
||||||
|
|
||||||
def generate_slug(pk: int) -> str:
|
|
||||||
if settings.SHORTENER_ADD_SLUG:
|
|
||||||
slug = generate_charset(length)
|
|
||||||
return slug + get_str_uuid(pk)
|
|
||||||
return get_str_uuid(pk)
|
|
||||||
|
|
||||||
|
|
||||||
def get_link_from_slug(slug: str, check_whole=False) -> Link | bool:
|
def get_link_from_slug(slug: str, check_whole=False) -> Link | bool:
|
||||||
if settings.SHORTENER_ADD_SLUG and not check_whole:
|
if settings.SHORTENER_ADD_SLUG and not check_whole:
|
||||||
payload = slug[length:]
|
payload = slug[length:]
|
||||||
|
|
|
@ -1,12 +1,22 @@
|
||||||
|
from django.conf import settings
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
|
||||||
from akarpov.tools.shortener.models import Link
|
from akarpov.tools.shortener.models import Link
|
||||||
from akarpov.tools.shortener.services import generate_slug
|
from akarpov.utils.generators import generate_charset, get_str_uuid
|
||||||
|
|
||||||
|
length = settings.SHORTENER_SLUG_LENGTH
|
||||||
|
|
||||||
|
|
||||||
|
def generate_slug(pk: int) -> str:
|
||||||
|
if settings.SHORTENER_ADD_SLUG:
|
||||||
|
slug = generate_charset(length)
|
||||||
|
return slug + get_str_uuid(pk)
|
||||||
|
return get_str_uuid(pk)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Link)
|
@receiver(post_save, sender=Link)
|
||||||
def link_on_create(sender, instance: Link, created, **kwargs):
|
def link_on_create(sender, instance, created, **kwargs):
|
||||||
if created:
|
if created:
|
||||||
instance.slug = generate_slug(instance.id)
|
instance.slug = generate_slug(instance.id)
|
||||||
instance.save(update_fields=["slug"])
|
instance.save(update_fields=["slug"])
|
||||||
|
|
|
@ -6,4 +6,5 @@
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", short_link_create_view, name="create"),
|
path("", short_link_create_view, name="create"),
|
||||||
|
path("revoked", short_link_create_view, name="revoked"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
||||||
from django.views.generic import CreateView, DetailView
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.views.generic import CreateView, DetailView, TemplateView
|
||||||
|
|
||||||
from akarpov.tools.shortener.forms import LinkForm
|
from akarpov.tools.shortener.forms import LinkForm
|
||||||
from akarpov.tools.shortener.models import Link
|
from akarpov.tools.shortener.models import Link
|
||||||
|
@ -35,3 +36,16 @@ def get_object(self, *args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
link_detail_view = LinkDetailView.as_view()
|
link_detail_view = LinkDetailView.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
class LinkRevokedView(TemplateView):
|
||||||
|
template_name = "shortener/revoked.html"
|
||||||
|
|
||||||
|
|
||||||
|
link_revoked_view = LinkRevokedView.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
def redirect_view(request, slug):
|
||||||
|
# TODO: move to faster framework, like FastApi
|
||||||
|
link = get_link_from_slug(slug)
|
||||||
|
return HttpResponseRedirect(link.source)
|
||||||
|
|
24
akarpov/users/migrations/0002_user_short_link.py
Normal file
24
akarpov/users/migrations/0002_user_short_link.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-15 12:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shortener", "0001_initial"),
|
||||||
|
("users", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="user",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
25
akarpov/users/migrations/0003_alter_user_short_link.py
Normal file
25
akarpov/users/migrations/0003_alter_user_short_link.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-15 12:39
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("shortener", "0001_initial"),
|
||||||
|
("users", "0002_user_short_link"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="user",
|
||||||
|
name="short_link",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="shortener.link",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,12 +1,13 @@
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.db.models import CharField, ImageField, TextField
|
from django.db.models import CharField, TextField
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from akarpov.utils.files import user_file_upload_mixin
|
from akarpov.common.models import BaseImageModel
|
||||||
|
from akarpov.tools.shortener.models import ShortLink
|
||||||
|
|
||||||
|
|
||||||
class User(AbstractUser):
|
class User(AbstractUser, BaseImageModel, ShortLink):
|
||||||
"""
|
"""
|
||||||
Default custom user model for akarpov.
|
Default custom user model for akarpov.
|
||||||
If adding fields that need to be filled at user signup,
|
If adding fields that need to be filled at user signup,
|
||||||
|
@ -16,8 +17,6 @@ class User(AbstractUser):
|
||||||
#: First and last name do not cover name patterns around the globe
|
#: First and last name do not cover name patterns around the globe
|
||||||
name = CharField(_("Name of User"), blank=True, max_length=255)
|
name = CharField(_("Name of User"), blank=True, max_length=255)
|
||||||
about = TextField(_("Description"), blank=True, max_length=100)
|
about = TextField(_("Description"), blank=True, max_length=100)
|
||||||
image = ImageField(upload_to=user_file_upload_mixin, blank=True)
|
|
||||||
image_cropped = ImageField(upload_to="cropped/", blank=True)
|
|
||||||
first_name = None # type: ignore
|
first_name = None # type: ignore
|
||||||
last_name = None # type: ignore
|
last_name = None # type: ignore
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
SpectacularSwaggerView,
|
SpectacularSwaggerView,
|
||||||
)
|
)
|
||||||
|
|
||||||
from akarpov.tools.shortener.views import link_detail_view
|
from akarpov.tools.shortener.views import redirect_view
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("home", TemplateView.as_view(template_name="pages/home.html"), name="home"),
|
path("home", TemplateView.as_view(template_name="pages/home.html"), name="home"),
|
||||||
|
@ -23,12 +23,13 @@
|
||||||
path(settings.ADMIN_URL, admin.site.urls),
|
path(settings.ADMIN_URL, admin.site.urls),
|
||||||
# User management
|
# User management
|
||||||
path("users/", include("akarpov.users.urls", namespace="users")),
|
path("users/", include("akarpov.users.urls", namespace="users")),
|
||||||
|
path("files/", include("akarpov.files.urls", namespace="files")),
|
||||||
path("forms/", include("akarpov.test_platform.urls", namespace="forms")),
|
path("forms/", include("akarpov.test_platform.urls", namespace="forms")),
|
||||||
path("tools/", include("akarpov.tools.urls", namespace="tools")),
|
path("tools/", include("akarpov.tools.urls", namespace="tools")),
|
||||||
path("ckeditor/", include("ckeditor_uploader.urls")),
|
path("ckeditor/", include("ckeditor_uploader.urls")),
|
||||||
path("accounts/", include("allauth.urls")),
|
path("accounts/", include("allauth.urls")),
|
||||||
path("", include("akarpov.blog.urls", namespace="blog")),
|
path("", include("akarpov.blog.urls", namespace="blog")),
|
||||||
path("s/<str:slug>", link_detail_view, name="short_url"),
|
path("s/<str:slug>", redirect_view, name="short_url"),
|
||||||
# Your stuff: custom urls includes go here
|
# Your stuff: custom urls includes go here
|
||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user