diff --git a/docker-compose.yaml b/docker-compose.yaml index 1e1f713..2742b8c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -34,6 +34,7 @@ services: max-file: "5" later42: + build: . container_name: later42 image: dntskdev/later42:master restart: always @@ -59,6 +60,28 @@ services: - "traefik.http.routers.later42-opt.tls.certresolver=myresolver" - "extdns.cf.later42.hostname=later42.com" +# later42_tasks: +# build: . +# container_name: later42_tasks +# image: dntskdev/later42:master +# restart: always +# command: celery -A later42 worker --loglevel=info +# environment: +# SECRET: "ahth3chaquodahh6que8thie1EThe5Iephich8eikei2Uojaemae6gee0kaet4aush2aoqu0ruL9oGhaiR9luu7cohreH6lebo0v" +# DB_TYPE: postgres +# DB_HOST: later42db +# DB_NAME: later42 +# DB_USER: later42 +# DB_PASS: later42 +# DOMAIN: later42.com +# READABILITY_HOST: http://ureadability:8080/ +# REDIS_URL: redis://redis:6379 +# logging: +# driver: json-file +# options: +# max-size: "10m" +# max-file: "5" + later42db: container_name: later42db image: postgres diff --git a/later42/migrations/0006_remove_url_content_remove_url_title_article_short_and_more.py b/later42/migrations/0006_remove_url_content_remove_url_title_article_short_and_more.py new file mode 100644 index 0000000..251ee97 --- /dev/null +++ b/later42/migrations/0006_remove_url_content_remove_url_title_article_short_and_more.py @@ -0,0 +1,31 @@ +# Generated by Django 4.1.2 on 2022-11-14 12:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('later42', '0005_rename_articles_article'), + ] + + operations = [ + migrations.RemoveField( + model_name='url', + name='content', + ), + migrations.RemoveField( + model_name='url', + name='title', + ), + migrations.AddField( + model_name='article', + name='short', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='article', + name='title', + field=models.CharField(blank=True, max_length=2000, null=True), + ), + ] diff --git a/later42/models/article.py b/later42/models/article.py index 97606d0..895eaf2 100644 --- a/later42/models/article.py +++ b/later42/models/article.py @@ -1,4 +1,3 @@ -from django.contrib.auth.models import User from django.db import models from later42.models.urls import URL @@ -7,3 +6,5 @@ class Article(models.Model): id = models.AutoField(auto_created=True, primary_key=True) url = models.ForeignKey(URL, on_delete=models.CASCADE) content = models.TextField(blank=True, null=True) + title = models.CharField(max_length=2000, blank=True, null=True) + short = models.TextField(blank=True, null=True) diff --git a/later42/models/urls.py b/later42/models/urls.py index 02deb17..c7c962b 100644 --- a/later42/models/urls.py +++ b/later42/models/urls.py @@ -8,6 +8,4 @@ class URL(models.Model): id = models.AutoField(auto_created=True, primary_key=True) user = models.ForeignKey(User, on_delete=models.CASCADE) url = models.CharField(max_length=2000) - title = models.CharField(max_length=2000) archived = models.BooleanField(default=False) - content = models.TextField(blank=True, null=True) diff --git a/later42/tasks.py b/later42/tasks.py index 936adb7..12b1c86 100644 --- a/later42/tasks.py +++ b/later42/tasks.py @@ -1,6 +1,7 @@ import os import pybrake from celery import shared_task +from django.contrib.auth.models import User from pybrake.middleware.celery import patch_celery from later42.models.urls import URL from later42.models.article import Article @@ -19,9 +20,17 @@ if AIRBRAKE_PROJECT_ID is not None and AIRBRAKE_PROJECT_KEY is not None: @shared_task() -def get_url_content_task(id): - url = URL.objects.get(id=id) - article = Article.objects.create(url=url) - content = get_content(url.url)['rich_content'] - article.content = content +def get_url_content_task(url, user_id): + print(url) + print(user_id) + user = User.objects.get(pk=int(user_id)) + url_object = URL(url=url, user=user) + url_object.save() + + data = get_content(url) + + article = Article.objects.create(url=url_object) + article.content = data['rich_content'] + article.title = data['title'] + article.short = data['excerpt'] article.save() diff --git a/later42/templates/archive.html b/later42/templates/archive.html index 4384d2f..a5c606f 100644 --- a/later42/templates/archive.html +++ b/later42/templates/archive.html @@ -2,54 +2,57 @@ {% block content %} <div class="post-preview"> -{% if urls|length > 0 %} -{% for url in urls %} +{% if data|length > 0 %} +{% for d in data %} <!-- Post preview--> <div class="post-preview"> <div class="d-flex justify-content-between"> <div class="p-2"> - <a href="{% url 'reader' url.id %}"> - <h2 class="post-title">{{ url.title }}</h2> + <a href="{% url 'reader' d.url.id %}"> + <h2 class="post-title">{% if d.title %}{{ d.title }}{% else %}Без заголовка{% endif %}</h2> </a> </div> <div class="p-2"> - <a href="/delete/{{ url.id }}"><span class="fa-regular fa-trash-can"></span></a> + <a href="/delete/{{ d.url.id }}"><span class="fa-regular fa-trash-can"></span></a> </div> </div> - {% if url.content %} + {% if d.short %} <p class="post-meta"> - {{ url.content }} + {{ d.short }} </p> {% endif %} <p class="post-meta"> - <a href="{{ url.url }}"> - {{ url.url }} + <a href="{{ d.url.url }}"> + {{ d.url.url }} </a> </p> </div> <!-- Divider--> <hr class="my-4" /> {% endfor %} + +{% if data.number %} <div class="pagination container row justify-content-end"> <div></div> <div class="step-links col-auto"> - {% if urls.has_previous %} + {% if data.has_previous %} <a href="?page=1">«</a> - <a href="?page={{ urls.previous_page_number }}">‹</a> + <a href="?page={{ data.previous_page_number }}">‹</a> {% endif %} <span class="current"> - страница {{ urls.number }} из {{ urls.paginator.num_pages }} + страница {{ data.number }} из {{ data.paginator.num_pages }} </span> - {% if urls.has_next %} - <a href="?page={{ urls.next_page_number }}">›</a> - <a href="?page={{ urls.paginator.num_pages }}">»</a> + {% if data.has_next %} + <a href="?page={{ data.next_page_number }}">›</a> + <a href="?page={{ data.paginator.num_pages }}">»</a> {% endif %} </div> </div> +{% endif %} {% else %} <h2 class="post-title">У вас нет ссылок в архиве</h2> {% endif %} </div> -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/later42/templates/base.html b/later42/templates/base.html index 06151af..1449360 100644 --- a/later42/templates/base.html +++ b/later42/templates/base.html @@ -57,6 +57,7 @@ <li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'about' %}">О нас</a></li> <li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'profile' %}">Профиль</a></li> <li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'archive' %}">Архив</a></li> + <li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'search' %}">Поиск</a></li> <li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'logout' %}">Выйти</a></li> {% else %} <li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'signup' %}">Регистрация</a></li> diff --git a/later42/templates/index.html b/later42/templates/index.html index 2977b3c..5a033ee 100644 --- a/later42/templates/index.html +++ b/later42/templates/index.html @@ -1,27 +1,27 @@ {% extends 'base.html' %} {% block content %} - {% if user.is_authenticated and urls|length > 0 %} - {% for url in urls %} + {% if user.is_authenticated and data|length > 0 %} + {% for d in data %} <!-- Post preview--> <div class="post-preview"> <div class="d-flex justify-content-between"> <div class="p-2"> - <a href="{% url 'reader' url.id %}"> - <h2 class="post-title">{{ url.title }}</h2> + <a href="{% url 'reader' d.url_id %}"> + <h2 class="post-title">{% if d.title %}{{ d.title }}{% else %}Без заголовка{% endif %}</h2> </a> </div> <div class="p-2"> - <a href="{% url 'archive_url' url.id %}"><span class="fa-regular fa-square-check"></span></a> + <a href="{% url 'archive_url' d.url_id %}"><span class="fa-regular fa-square-check"></span></a> </div> </div> - {% if url.content %} + {% if d.short %} <p class="post-meta"> - {{ url.content }} + {{ d.short }} </p> {% endif %} <p class="post-meta"> - {{ url.url|urlizetrunc:70 }} + {{ d.url.url|urlizetrunc:70 }} </p> </div> <!-- Divider--> diff --git a/later42/templates/search.html b/later42/templates/search.html new file mode 100644 index 0000000..758ce5f --- /dev/null +++ b/later42/templates/search.html @@ -0,0 +1,58 @@ +{% extends 'base.html' %} + +{% block title %}Поиск{% endblock %} + + +{% block content %} +<form action="{% url 'search' %}" method="post"> + {% csrf_token %} + <input type="text" name="search" placeholder="Что ищем?"> + <input type="submit" value="Искать" /> +</form> +<br /> + {% for d in data %} + <!-- Post preview--> + <div class="post-preview"> + <div class="d-flex justify-content-between"> + <div class="p-2"> + <a href="{% url 'reader' d.url.id %}"> + <h2 class="post-title">{{ d.title }}</h2> + </a> + </div> + <div class="p-2"> + <a href="{% url 'archive_url' d.url.id %}"><span class="fa-regular fa-square-check"></span></a> + </div> + </div> + {% if d.short %} + <p class="post-meta"> + {{ d.short }} + </p> + {% endif %} + <p class="post-meta"> + {{ d.url.url|urlizetrunc:70 }} + </p> + </div> + <!-- Divider--> + <hr class="my-4" /> + {% endfor %} +{% if data.number %} +<div class="pagination container row justify-content-end"> + <div></div> + <div class="step-links col-auto"> + {% if data.has_previous %} + <a href="?page=1">«</a> + <a href="?page={{ data.previous_page_number }}">‹</a> + {% endif %} + + <span class="current"> + страница {{ data.number }} из {{ data.paginator.num_pages }} + </span> + + {% if data.has_next %} + <a href="?page={{ data.next_page_number }}">›</a> + <a href="?page={{ data.paginator.num_pages }}">»</a> + {% endif %} + </div> +</div> +{% endif %} +{% endblock %} diff --git a/later42/urls.py b/later42/urls.py index fd49e48..2fd712b 100644 --- a/later42/urls.py +++ b/later42/urls.py @@ -22,7 +22,7 @@ from django.contrib.auth.models import User from rest_framework import routers, serializers, viewsets # from later42.forms import CustomLoginForm -from later42.views import account_activation, index, profile, api, api_token, reader, signup, about +from later42.views import account_activation, index, profile, api, api_token, reader, search, signup, about class UserSerializer(serializers.HyperlinkedModelSerializer): @@ -54,4 +54,5 @@ urlpatterns = [ path('archive/', index.archive, name='archive'), path('archive/<int:url_id>', index.archive, name='archive_url'), path('reader/<int:url_id>', reader.get, name='reader'), + path('search/', search.search, name='search'), ] diff --git a/later42/views/api.py b/later42/views/api.py index 95f2686..26a23cb 100644 --- a/later42/views/api.py +++ b/later42/views/api.py @@ -8,26 +8,8 @@ from django.conf import settings class URL(APIView): def post(self, request, format=None): - url = request.GET.get('url') - if url: - page = get_content(url) - - try: - title = page['title'] - except KeyError: - title = '' - - content = None - if settings.READABILITY_HOST: - try: - content = page['excerpt'] - except KeyError: - content = '' - - url = URLModel(url=url, user=request.user, - title=title, content=content) - url.save() - get_url_content_task.delay(url.id) + if request.GET.get('url'): + get_url_content_task.delay(request.GET.get('url'), request.user.id) return Response({'status': 'success'}) else: return Response({'status': 'error'}) diff --git a/later42/views/index.py b/later42/views/index.py index 70eea5b..4ed26be 100644 --- a/later42/views/index.py +++ b/later42/views/index.py @@ -3,16 +3,20 @@ from django.contrib.auth.decorators import login_required from django.shortcuts import render, redirect from django.core.paginator import Paginator from django.conf import settings + +from later42.models.article import Article from later42.models.urls import URL def get(request): + data = {} try: urls = URL.objects.filter( user=request.user, archived=False).order_by('-id') + data = Article.objects.filter(url__in=urls).select_related('url') except: urls = [] - context = {'urls': urls} + context = {'data': data} return render(request, 'index.html', context) @@ -24,12 +28,13 @@ def archive(request, url_id=None): try: urls = URL.objects.filter( user=request.user, archived=True).order_by('-id') - paginator = Paginator(urls, settings.URLS_PER_PAGE) + data = Article.objects.filter(url__in=urls).select_related('url') + paginator = Paginator(data, settings.URLS_PER_PAGE) page_number = request.GET.get('page') - urls = paginator.get_page(page_number) + data = paginator.get_page(page_number) except: urls = [] - context = {'urls': urls} + context = {'data': data} return render(request, 'archive.html', context) diff --git a/later42/views/reader.py b/later42/views/reader.py index 12da6e7..4fb70ca 100644 --- a/later42/views/reader.py +++ b/later42/views/reader.py @@ -6,16 +6,13 @@ from django.conf import settings from later42.libs.content import get_content, sanitize_img_size from later42.models.article import Article from later42.models.urls import URL -from later42.tasks import get_url_content_task @login_required def get(request, url_id=None): url = URL.objects.get( user=request.user, id=url_id) - content = {} - try: article = Article.objects.get(url=url) content['rich_content'] = article.content @@ -24,6 +21,5 @@ def get(request, url_id=None): content['rich_content'] = sanitize_img_size(content['rich_content']) except: content = get_content(url.url) - get_url_content_task.delay(url.id) context = {'url': url, 'content': content} return render(request, 'reader.html', context) diff --git a/later42/views/search.py b/later42/views/search.py new file mode 100644 index 0000000..cef0728 --- /dev/null +++ b/later42/views/search.py @@ -0,0 +1,29 @@ +from django.conf import settings +from django.contrib.auth.decorators import login_required +from django.core.paginator import Paginator +from django.db.models import Q +from django.shortcuts import render + +from later42.models.article import Article +from later42.models.urls import URL as URL + + +@login_required +def search(request): + pattern = request.POST.get('search') + context = {} + if request.method == 'GET': + return render(request, 'search.html', context) + elif request.method == 'POST': + urls = URL.objects.filter( + user=request.user).order_by('-id') + data = Article.objects.filter( + Q(title__contains=pattern) | + Q(content__contains=pattern) | + Q(short__contains=pattern) | + Q(url__url__contains=pattern), url__user_id=request.user.id).select_related('url') + paginator = Paginator(data, settings.URLS_PER_PAGE) + page_number = request.GET.get('page') + data = paginator.get_page(page_number) + context = {'data': data} + return render(request, 'search.html', context)