Skip to content

Commit

Permalink
add news
Browse files Browse the repository at this point in the history
  • Loading branch information
d2avids committed Aug 9, 2024
1 parent af5de19 commit 350fe42
Show file tree
Hide file tree
Showing 15 changed files with 176 additions and 5 deletions.
Binary file modified backend/_db.sqlite3
Binary file not shown.
2 changes: 1 addition & 1 deletion backend/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ class Meta:
class NewsSerializer(serializers.ModelSerializer):
class Meta:
model = News
fields = ('id', 'title', ' description', 'image', 'text', 'created_at')
fields = ('id', 'title', 'description', 'image', 'text', 'created_at')
1 change: 1 addition & 0 deletions backend/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
router.register(r'answers/(?P<child_or_group_id>\d+)',
task_views.TaskAnswerViewSet, basename='answers')
router.register(r'regions', views.RegionViewSet, basename='regions')
router.register(r'news', views.NewsViewSet, basename='news')


urlpatterns = [
Expand Down
5 changes: 5 additions & 0 deletions backend/api/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination


class Limit100OffsetPagination(LimitOffsetPagination):
max_limit = 100
25 changes: 23 additions & 2 deletions backend/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
from rest_framework import permissions

from api.mixins import RetrieveListViewSet
from api.serializers import TaskSerializer, RegionSerializer
from api.serializers import TaskSerializer, RegionSerializer, ShortNewsSerializer, NewsSerializer
from api.utils import Limit100OffsetPagination
from news.models import News
from tasks.models import Task
from users.models import Region

Expand All @@ -15,6 +17,25 @@ class TaskViewSet(RetrieveListViewSet):
serializer_class = TaskSerializer
permission_classes = (permissions.AllowAny,)

@method_decorator(cache_page(settings.TASKS_LIST_TTL))
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)


class NewsViewSet(RetrieveListViewSet):
queryset = News.objects.all()
permission_classes = (permissions.AllowAny,)
pagination_class = Limit100OffsetPagination

def get_serializer_class(self):
match self.action:
case 'list':
return ShortNewsSerializer
case 'retrieve':
return NewsSerializer
case _:
return NewsSerializer


class RegionViewSet(RetrieveListViewSet):
"""Представляет регионы. Доступны только операции чтения."""
Expand All @@ -23,7 +44,7 @@ class RegionViewSet(RetrieveListViewSet):
serializer_class = RegionSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('name',)
permission_classes = (permissions.AllowAny,)
permission_classes = (permissions.IsAuthenticated,)
ordering = ('name',)

@method_decorator(cache_page(settings.REGIONS_LIST_TTL))
Expand Down
6 changes: 4 additions & 2 deletions backend/backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
REGIONS_LIST_TTL = 60
REGIONS_LIST_TTL = 120
TASKS_LIST_TTL = 120

SECRET_KEY = os.getenv('SECRET_KEY', default='key')

Expand Down Expand Up @@ -43,7 +44,8 @@
INSTALLED_APPS += [
'users.apps.UsersConfig',
'tasks.apps.TasksConfig',
'api.apps.ApiConfig'
'api.apps.ApiConfig',
'news.apps.NewsConfig'
]

MIDDLEWARE = [
Expand Down
Empty file added backend/news/__init__.py
Empty file.
17 changes: 17 additions & 0 deletions backend/news/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django.contrib import admin
from django.utils.safestring import mark_safe

from news.models import News


@admin.register(News)
class NewsAdmin(admin.ModelAdmin):
list_display = ('id', 'title', 'image', 'created_at',)
search_fields = ('title', 'description')

def image_tag(self, obj):
if obj.image:
return mark_safe(f'<img src="{obj.image.url}" width="150" height="auto" />')
return "No Image"

image_tag.short_description = 'Изображение'
7 changes: 7 additions & 0 deletions backend/news/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.apps import AppConfig


class NewsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'news'
verbose_name = 'Новости'
30 changes: 30 additions & 0 deletions backend/news/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 5.0.6 on 2024-08-09 18:10

import news.models
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='News',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255, verbose_name='Заголовок')),
('image', models.ImageField(upload_to=news.models.news_files_path, verbose_name='Изображение')),
('description', models.CharField(max_length=500, verbose_name='Краткое содержание')),
('text', models.TextField(verbose_name='Текст')),
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
],
options={
'verbose_name': 'Новость',
'verbose_name_plural': 'Новости',
},
),
]
17 changes: 17 additions & 0 deletions backend/news/migrations/0002_alter_news_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.0.6 on 2024-08-09 18:15

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('news', '0001_initial'),
]

operations = [
migrations.AlterModelOptions(
name='news',
options={'ordering': ('-created_at',), 'verbose_name': 'Новость', 'verbose_name_plural': 'Новости'},
),
]
Empty file.
30 changes: 30 additions & 0 deletions backend/news/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from django.db import models


def news_files_path(instance, filename) -> str:
"""Функция для формирования пути сохранения изображения.
:param instance: Экземпляр модели.
:param filename: Имя файла.
:return: Путь к файлу.
"""
filename = filename.split('.')
last_news_instance = News.objects.last()
instance_id = last_news_instance.id+1 if last_news_instance else 1
return f'news/{instance_id}/{filename[0][:20]}.{filename[1]}'


class News(models.Model):
title = models.CharField(max_length=255, verbose_name='Заголовок')
image = models.ImageField(verbose_name='Изображение', upload_to=news_files_path)
description = models.CharField(max_length=500, verbose_name='Краткое содержание')
text = models.TextField(verbose_name='Текст')
created_at = models.DateTimeField(verbose_name='Дата создания', auto_now_add=True)

class Meta:
verbose_name = 'Новость'
verbose_name_plural = 'Новости'
ordering = ('-created_at',)

def __str__(self):
return self.title
18 changes: 18 additions & 0 deletions backend/tasks/migrations/0004_alter_taskanswer_is_started.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.6 on 2024-08-09 18:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('tasks', '0003_alter_task_name_alter_taskanswer_is_correct'),
]

operations = [
migrations.AlterField(
model_name='taskanswer',
name='is_started',
field=models.BooleanField(default=True, verbose_name='Задание начато'),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.0.6 on 2024-08-09 18:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('users', '0008_rename_user_id_child_user_and_more'),
]

operations = [
migrations.AlterField(
model_name='user',
name='email',
field=models.EmailField(max_length=254, unique=True, verbose_name='Email'),
),
migrations.AlterField(
model_name='user',
name='tasks_type',
field=models.CharField(choices=[('индивидуальный', 'индивидуальный'), ('групповой', 'групповой')], max_length=20, verbose_name='Формат занятий'),
),
]

0 comments on commit 350fe42

Please sign in to comment.