Add package files
This commit is contained in:
0
extend/__init__.py
Normal file
0
extend/__init__.py
Normal file
22
extend/admin.py
Normal file
22
extend/admin.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from django.contrib import admin
|
||||
from mptt.admin import MPTTModelAdmin
|
||||
|
||||
|
||||
class CategoryModelAdmin(MPTTModelAdmin):
|
||||
list_display = ("id", "name", "slug")
|
||||
|
||||
|
||||
class TagModelAdmin(admin.ModelAdmin):
|
||||
list_display = ("id", "name", "slug")
|
||||
|
||||
|
||||
def toggle_status_published(modeladmin, request, queryset):
|
||||
queryset.update(status="published")
|
||||
|
||||
|
||||
def toggle_status_moderation(modeladmin, request, queryset):
|
||||
queryset.update(status="moderation")
|
||||
|
||||
|
||||
toggle_status_published.short_description = "Опубликовать"
|
||||
toggle_status_moderation.short_description = "Отправить на модерацию"
|
||||
5
extend/apps.py
Normal file
5
extend/apps.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ExtendConfig(AppConfig):
|
||||
name = "extend"
|
||||
0
extend/migrations/__init__.py
Normal file
0
extend/migrations/__init__.py
Normal file
131
extend/models.py
Normal file
131
extend/models.py
Normal file
@@ -0,0 +1,131 @@
|
||||
from datetime import datetime
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.safestring import mark_safe
|
||||
from mptt.models import MPTTModel, TreeForeignKey
|
||||
from pytils.translit import slugify
|
||||
from model_utils import Choices
|
||||
from easy_thumbnails.files import get_thumbnailer
|
||||
from easy_thumbnails.fields import ThumbnailerImageField
|
||||
|
||||
|
||||
class Category(MPTTModel):
|
||||
name = models.CharField(
|
||||
"Название", unique=True, max_length=100
|
||||
)
|
||||
slug = models.SlugField(
|
||||
"Путь",
|
||||
null=True,
|
||||
blank=True,
|
||||
unique=True,
|
||||
max_length=100,
|
||||
)
|
||||
parent = TreeForeignKey(
|
||||
"self",
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="children",
|
||||
)
|
||||
|
||||
class MPTTMeta:
|
||||
order_insertion_by = ["name"]
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
verbose_name = "Категория"
|
||||
verbose_name_plural = "Категории"
|
||||
ordering = ["name"]
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.slug:
|
||||
self.slug = slugify(self.name)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class Tag(models.Model):
|
||||
name = models.CharField(
|
||||
"Название", unique=True, max_length=100
|
||||
)
|
||||
slug = models.SlugField(
|
||||
"Путь",
|
||||
null=True,
|
||||
blank=True,
|
||||
unique=True,
|
||||
max_length=100,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
verbose_name = "Метка"
|
||||
verbose_name_plural = "Метки"
|
||||
ordering = ["name"]
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.slug:
|
||||
self.slug = slugify(self.name)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class Photo(models.Model):
|
||||
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL, verbose_name="Пользователь")
|
||||
title = models.CharField("Название", blank=True, max_length=255)
|
||||
image = ThumbnailerImageField(
|
||||
"Фото", upload_to="photos/", max_length=255, default="", resize_source=dict(size=(825, 825), sharpen=True)
|
||||
)
|
||||
created = models.DateTimeField("Создано", default=datetime.now)
|
||||
updated = models.DateTimeField("Изменено", auto_now=True)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
verbose_name = "Фотография"
|
||||
verbose_name_plural = "Фотографии"
|
||||
ordering = ["id"]
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
def image_tag(self):
|
||||
if self.image:
|
||||
options = {'size': (100, 100), 'upscale': True}
|
||||
thumb_url = get_thumbnailer(self.image).get_thumbnail(options).url
|
||||
return mark_safe('<img src="%s"/>' % thumb_url)
|
||||
else:
|
||||
return 'Изображение отсутствует'
|
||||
|
||||
image_tag.short_description = 'Превью'
|
||||
|
||||
|
||||
class Comment(models.Model):
|
||||
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
|
||||
text = models.TextField("Текст")
|
||||
created = models.DateTimeField(
|
||||
"Создано", auto_now_add=True
|
||||
)
|
||||
updated = models.DateTimeField(
|
||||
"Изменено", auto_now=True
|
||||
)
|
||||
STATUS = Choices(
|
||||
("moderation", "На модерации"),
|
||||
("published", "Опубликовано"),
|
||||
)
|
||||
status = models.CharField(
|
||||
choices=STATUS,
|
||||
default=STATUS.moderation,
|
||||
max_length=20,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
verbose_name = "Комментарий"
|
||||
verbose_name_plural = "Комментарии"
|
||||
ordering = ["-created"]
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.created} {self.user.username}'
|
||||
0
extend/tests.py
Normal file
0
extend/tests.py
Normal file
25
extend/utils.py
Normal file
25
extend/utils.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import re
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
def validate_url(value):
|
||||
"""
|
||||
Валидация ссылок на видео с видеохостинга YouTube
|
||||
"""
|
||||
video_url = value
|
||||
regex = re.compile(
|
||||
r"(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?(?P<id>[A-Za-z0-9\-=_]{11})"
|
||||
)
|
||||
match = regex.match(video_url)
|
||||
if not match:
|
||||
raise ValidationError(
|
||||
_("%(value)s не является корректной YouTube ссылкой"),
|
||||
params={"value": value},
|
||||
)
|
||||
|
||||
|
||||
def generate_secret_key():
|
||||
chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)"
|
||||
return get_random_string(50, chars)
|
||||
0
extend/views.py
Normal file
0
extend/views.py
Normal file
Reference in New Issue
Block a user