delayed add url and search

This commit is contained in:
Silver Ghost 2022-11-14 20:03:13 +03:00
parent 9904586ea0
commit dddbb034e5
No known key found for this signature in database
14 changed files with 198 additions and 61 deletions

View File

@ -34,6 +34,7 @@ services:
max-file: "5" max-file: "5"
later42: later42:
build: .
container_name: later42 container_name: later42
image: dntskdev/later42:master image: dntskdev/later42:master
restart: always restart: always
@ -59,6 +60,28 @@ services:
- "traefik.http.routers.later42-opt.tls.certresolver=myresolver" - "traefik.http.routers.later42-opt.tls.certresolver=myresolver"
- "extdns.cf.later42.hostname=later42.com" - "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: later42db:
container_name: later42db container_name: later42db
image: postgres image: postgres

View File

@ -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),
),
]

View File

@ -1,4 +1,3 @@
from django.contrib.auth.models import User
from django.db import models from django.db import models
from later42.models.urls import URL from later42.models.urls import URL
@ -7,3 +6,5 @@ class Article(models.Model):
id = models.AutoField(auto_created=True, primary_key=True) id = models.AutoField(auto_created=True, primary_key=True)
url = models.ForeignKey(URL, on_delete=models.CASCADE) url = models.ForeignKey(URL, on_delete=models.CASCADE)
content = models.TextField(blank=True, null=True) content = models.TextField(blank=True, null=True)
title = models.CharField(max_length=2000, blank=True, null=True)
short = models.TextField(blank=True, null=True)

View File

@ -8,6 +8,4 @@ class URL(models.Model):
id = models.AutoField(auto_created=True, primary_key=True) id = models.AutoField(auto_created=True, primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE)
url = models.CharField(max_length=2000) url = models.CharField(max_length=2000)
title = models.CharField(max_length=2000)
archived = models.BooleanField(default=False) archived = models.BooleanField(default=False)
content = models.TextField(blank=True, null=True)

View File

@ -1,6 +1,7 @@
import os import os
import pybrake import pybrake
from celery import shared_task from celery import shared_task
from django.contrib.auth.models import User
from pybrake.middleware.celery import patch_celery from pybrake.middleware.celery import patch_celery
from later42.models.urls import URL from later42.models.urls import URL
from later42.models.article import Article 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() @shared_task()
def get_url_content_task(id): def get_url_content_task(url, user_id):
url = URL.objects.get(id=id) print(url)
article = Article.objects.create(url=url) print(user_id)
content = get_content(url.url)['rich_content'] user = User.objects.get(pk=int(user_id))
article.content = content 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() article.save()

View File

@ -2,52 +2,55 @@
{% block content %} {% block content %}
<div class="post-preview"> <div class="post-preview">
{% if urls|length > 0 %} {% if data|length > 0 %}
{% for url in urls %} {% for d in data %}
<!-- Post preview--> <!-- Post preview-->
<div class="post-preview"> <div class="post-preview">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div class="p-2"> <div class="p-2">
<a href="{% url 'reader' url.id %}"> <a href="{% url 'reader' d.url.id %}">
<h2 class="post-title">{{ url.title }}</h2> <h2 class="post-title">{% if d.title %}{{ d.title }}{% else %}Без заголовка{% endif %}</h2>
</a> </a>
</div> </div>
<div class="p-2"> <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>
</div> </div>
{% if url.content %} {% if d.short %}
<p class="post-meta"> <p class="post-meta">
{{ url.content }} {{ d.short }}
</p> </p>
{% endif %} {% endif %}
<p class="post-meta"> <p class="post-meta">
<a href="{{ url.url }}"> <a href="{{ d.url.url }}">
{{ url.url }} {{ d.url.url }}
</a> </a>
</p> </p>
</div> </div>
<!-- Divider--> <!-- Divider-->
<hr class="my-4" /> <hr class="my-4" />
{% endfor %} {% endfor %}
{% if data.number %}
<div class="pagination container row justify-content-end"> <div class="pagination container row justify-content-end">
<div></div> <div></div>
<div class="step-links col-auto"> <div class="step-links col-auto">
{% if urls.has_previous %} {% if data.has_previous %}
<a href="?page=1">&laquo;</a> <a href="?page=1">&laquo;</a>
<a href="?page={{ urls.previous_page_number }}">&lsaquo;</a> <a href="?page={{ data.previous_page_number }}">&lsaquo;</a>
{% endif %} {% endif %}
<span class="current"> <span class="current">
страница {{ urls.number }} из {{ urls.paginator.num_pages }} страница {{ data.number }} из {{ data.paginator.num_pages }}
</span> </span>
{% if urls.has_next %} {% if data.has_next %}
<a href="?page={{ urls.next_page_number }}">&rsaquo;</a> <a href="?page={{ data.next_page_number }}">&rsaquo;</a>
<a href="?page={{ urls.paginator.num_pages }}">&raquo;</a> <a href="?page={{ data.paginator.num_pages }}">&raquo;</a>
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% endif %}
{% else %} {% else %}
<h2 class="post-title">У вас нет ссылок в архиве</h2> <h2 class="post-title">У вас нет ссылок в архиве</h2>
{% endif %} {% endif %}

View File

@ -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 '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 '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 '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> <li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'logout' %}">Выйти</a></li>
{% else %} {% else %}
<li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'signup' %}">Регистрация</a></li> <li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="{% url 'signup' %}">Регистрация</a></li>

View File

@ -1,27 +1,27 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
{% if user.is_authenticated and urls|length > 0 %} {% if user.is_authenticated and data|length > 0 %}
{% for url in urls %} {% for d in data %}
<!-- Post preview--> <!-- Post preview-->
<div class="post-preview"> <div class="post-preview">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div class="p-2"> <div class="p-2">
<a href="{% url 'reader' url.id %}"> <a href="{% url 'reader' d.url_id %}">
<h2 class="post-title">{{ url.title }}</h2> <h2 class="post-title">{% if d.title %}{{ d.title }}{% else %}Без заголовка{% endif %}</h2>
</a> </a>
</div> </div>
<div class="p-2"> <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>
</div> </div>
{% if url.content %} {% if d.short %}
<p class="post-meta"> <p class="post-meta">
{{ url.content }} {{ d.short }}
</p> </p>
{% endif %} {% endif %}
<p class="post-meta"> <p class="post-meta">
{{ url.url|urlizetrunc:70 }} {{ d.url.url|urlizetrunc:70 }}
</p> </p>
</div> </div>
<!-- Divider--> <!-- Divider-->

View File

@ -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">&laquo;</a>
<a href="?page={{ data.previous_page_number }}">&lsaquo;</a>
{% endif %}
<span class="current">
страница {{ data.number }} из {{ data.paginator.num_pages }}
</span>
{% if data.has_next %}
<a href="?page={{ data.next_page_number }}">&rsaquo;</a>
<a href="?page={{ data.paginator.num_pages }}">&raquo;</a>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}

View File

@ -22,7 +22,7 @@ from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets from rest_framework import routers, serializers, viewsets
# from later42.forms import CustomLoginForm # 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): class UserSerializer(serializers.HyperlinkedModelSerializer):
@ -54,4 +54,5 @@ urlpatterns = [
path('archive/', index.archive, name='archive'), path('archive/', index.archive, name='archive'),
path('archive/<int:url_id>', index.archive, name='archive_url'), path('archive/<int:url_id>', index.archive, name='archive_url'),
path('reader/<int:url_id>', reader.get, name='reader'), path('reader/<int:url_id>', reader.get, name='reader'),
path('search/', search.search, name='search'),
] ]

View File

@ -8,26 +8,8 @@ from django.conf import settings
class URL(APIView): class URL(APIView):
def post(self, request, format=None): def post(self, request, format=None):
url = request.GET.get('url') if request.GET.get('url'):
if url: get_url_content_task.delay(request.GET.get('url'), request.user.id)
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)
return Response({'status': 'success'}) return Response({'status': 'success'})
else: else:
return Response({'status': 'error'}) return Response({'status': 'error'})

View File

@ -3,16 +3,20 @@ from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.conf import settings from django.conf import settings
from later42.models.article import Article
from later42.models.urls import URL from later42.models.urls import URL
def get(request): def get(request):
data = {}
try: try:
urls = URL.objects.filter( urls = URL.objects.filter(
user=request.user, archived=False).order_by('-id') user=request.user, archived=False).order_by('-id')
data = Article.objects.filter(url__in=urls).select_related('url')
except: except:
urls = [] urls = []
context = {'urls': urls} context = {'data': data}
return render(request, 'index.html', context) return render(request, 'index.html', context)
@ -24,12 +28,13 @@ def archive(request, url_id=None):
try: try:
urls = URL.objects.filter( urls = URL.objects.filter(
user=request.user, archived=True).order_by('-id') 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') page_number = request.GET.get('page')
urls = paginator.get_page(page_number) data = paginator.get_page(page_number)
except: except:
urls = [] urls = []
context = {'urls': urls} context = {'data': data}
return render(request, 'archive.html', context) return render(request, 'archive.html', context)

View File

@ -6,16 +6,13 @@ from django.conf import settings
from later42.libs.content import get_content, sanitize_img_size from later42.libs.content import get_content, sanitize_img_size
from later42.models.article import Article from later42.models.article import Article
from later42.models.urls import URL from later42.models.urls import URL
from later42.tasks import get_url_content_task
@login_required @login_required
def get(request, url_id=None): def get(request, url_id=None):
url = URL.objects.get( url = URL.objects.get(
user=request.user, id=url_id) user=request.user, id=url_id)
content = {} content = {}
try: try:
article = Article.objects.get(url=url) article = Article.objects.get(url=url)
content['rich_content'] = article.content content['rich_content'] = article.content
@ -24,6 +21,5 @@ def get(request, url_id=None):
content['rich_content'] = sanitize_img_size(content['rich_content']) content['rich_content'] = sanitize_img_size(content['rich_content'])
except: except:
content = get_content(url.url) content = get_content(url.url)
get_url_content_task.delay(url.id)
context = {'url': url, 'content': content} context = {'url': url, 'content': content}
return render(request, 'reader.html', context) return render(request, 'reader.html', context)

29
later42/views/search.py Normal file
View File

@ -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)