Compare commits

...

3 Commits

  1. 3
      cms/__init__.py
  2. 15
      cms/celery.py
  3. 3
      cms/forms.py
  4. 3
      cms/models.py
  5. 19
      cms/tasks.py
  6. 31
      cms/templates/articles/new.html
  7. 20
      cms/templates/articles/planned.html
  8. 7
      cms/urls.py
  9. 59
      cms/views.py
  10. 7
      crossposting_backend/settings.py
  11. 4
      requirements.txt

3
cms/__init__.py

@ -0,0 +1,3 @@
from .celery import app as celery_app
__all__ = ('celery_app')

15
cms/celery.py

@ -0,0 +1,15 @@
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'crossposting_backend.settings')
CELERY_TIMEZONE = 'Europe/Moscow'
app = Celery('cms')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print(f'Requestgit {self.request!r}')

3
cms/forms.py

@ -7,10 +7,11 @@ from .models import Article
class ArticleForm(forms.ModelForm):
link_widget = forms.TextInput(attrs={'placeholder': 'Введите ссылку новости'})
link = forms.CharField(widget=link_widget)
publication_time = forms.DateTimeField(widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}), required=False)
class Meta:
model = Article
fields = ('body', 'link',)
fields = ('body', 'link', 'publication_time')
class UserForm(forms.ModelForm):

3
cms/models.py

@ -2,5 +2,8 @@ from django.db import models
class Article(models.Model):
id = models.BigAutoField(primary_key=True)
body = models.TextField(null=False)
link = models.CharField(max_length=200, null=False)
publication_time = models.DateTimeField(blank=True, null=True)
is_published = models.BooleanField(default=False)

19
cms/tasks.py

@ -0,0 +1,19 @@
from cms import promoters
from cms.models import Article
from celery import shared_task
@shared_task
def promote_post(article_id):
article = Article.objects.get(id=article_id)
article.is_published = True
article.save()
marketer = promoters.Marketer(article)
marketer.promote()
@shared_task
def delayed_post(article_id, publication_time):
article = Article.objects.get(id=article_id)
celery_task = promote_post.apply_async(args=[article.id], eta=publication_time)
return celery_task.id

31
cms/templates/articles/new.html

@ -17,17 +17,34 @@
<div class="row">
<div class="col">
<button
class="btn btn-primary"
type="submit"
disabled="disabled"
>
Продвинуть
class="btn btn-primary"
type="submit"
id="submit-button">
{% if new_article_form.publication_time.value %}
disabled="disabled"
{% endif %}
{% if new_article_form.publication_time.value %}
Запланировать
{% else %}
Опубликовать сейчас
{% endif %}
</button>
&nbsp;
<a href="{% url 'planned' %}" class="btn btn-primary">Список отложенных публикаций</a>
</div>
<script>
document.getElementById("id_publication_time").addEventListener("change", function() {
var submitButton = document.getElementById("submit-button");
if (this.value) {
submitButton.innerHTML = "Запланировать";
} else {
submitButton.innerHTML = "Опубликовать";
}
});
</script>
<div id="vkShare" class="col"></div>
</div>
{% endbuttons %}
</form>
</div>
@ -42,7 +59,6 @@
}
const appendShare = (e) => {
submitBtn.disabled = true
const articleLink = e.target.value;
const gen = {
url: articleLink
@ -57,7 +73,6 @@
}
const main = () => {
submitBtn = document.querySelector('button[type="submit"]')
const linkInput = document.querySelector('[name="link"]');
linkInput.addEventListener('input', appendShare)
linkInput.addEventListener('paste', appendShare)

20
cms/templates/articles/planned.html

@ -0,0 +1,20 @@
{% extends 'base.html' %}
{% load bootstrap5 %}
{% block content %}
<div class="container">
<a href="{% url 'new-article' %}" class="btn btn-primary">Вернуться</a>
&nbsp;
{% for article in post %}
<div class="card mb-3">
<div class="card-body">
<p class="card-text">{{ article.body }}</p>
<a href="{{ article.link }}">{{ article.link }}</a>
<p class="card-text"><small class="text-muted">Дата публикации: {{ article.publication_time }}</small></p>
{% if user.is_authenticated %}
<a href="{% url 'article_delete' article.id %}" class="btn btn-danger">Удалить</a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endblock content %}

7
cms/urls.py

@ -1,6 +1,5 @@
from django.urls import path
from .views import ArticleView, new_article, AuthenticationView
from .views import ArticleView, new_article, AuthenticationView, plannedView, articleDelete
urlpatterns = [
path('articles/', ArticleView.as_view(), name='create-article'),
@ -9,5 +8,7 @@ urlpatterns = [
'',
AuthenticationView.as_view(),
name='authenticate'
)
),
path('articles/planned/', plannedView, name='planned'),
path('articles/article_delete/<int:id>/', articleDelete, name='article_delete'),
]

59
cms/views.py

@ -3,31 +3,52 @@ from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpRequest, HttpResponseRedirect
from django.shortcuts import render
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from requests import request
from cms import promoters
from cms.forms import ArticleForm, UserForm
from cms.models import Article
from cms.tasks import delayed_post
from datetime import datetime, timezone
class ArticleView(LoginRequiredMixin, View):
def post(self, request: HttpRequest):
post_data = request.POST
article = Article.objects.create(body=post_data['body'],
link=post_data['link'])
marketer = promoters.Marketer(article)
try:
marketer.promote()
message_type = messages.SUCCESS
message_text = 'Продвижение статьи прошло успешно'
except promoters.PromoteError as exc:
message_type = messages.ERROR
message_text = 'Произошла ошибка: %s' % str(exc)
messages.add_message(request=request,
level=message_type,
message=message_text)
if 'publication_time' not in post_data or post_data['publication_time'] == "":
# Значение publication_time не указано
article = Article.objects.create(body=post_data['body'],
link=post_data['link'],
publication_time=datetime.now())
marketer = promoters.Marketer(article)
try:
marketer.promote()
article.is_published = 1
message_type = messages.SUCCESS
message_text = 'Продвижение статьи прошло успешно'
article.is_published = True
article.save()
except promoters.PromoteError as exc:
message_type = messages.ERROR
message_text = 'Произошла ошибка: %s' % str(exc)
messages.add_message(request=request,
level=message_type,
message=message_text)
else:
# Значение publication_time указано
publication_time = post_data['publication_time']
publication_time = datetime.fromisoformat(publication_time)
publication_time = publication_time.astimezone(timezone.utc)
article = Article.objects.create(body=post_data['body'],
link=post_data['link'],
publication_time=publication_time)
delayed_post.apply_async(args=(article.id, publication_time), eta=publication_time)
return HttpResponseRedirect(reverse('new-article'))
@ -69,3 +90,13 @@ class AuthenticationView(View):
login(request,
user=authenticated_user)
return HttpResponseRedirect(reverse('new-article'))
def plannedView(request):
data = Article.objects.filter(is_published=False)
return render(request, 'articles/planned.html', context={'post':data})
def articleDelete(request, id):
article = Article.objects.get(id=id)
article.delete()
return redirect('planned')

7
crossposting_backend/settings.py

@ -14,6 +14,7 @@ from os import path, getenv
from pathlib import Path
import dotenv
from celery.schedules import crontab
from django.core import signing
from .private.settings import *
@ -72,6 +73,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'cms',
'bootstrap5',
'django_celery_beat',
]
MIDDLEWARE = [
@ -137,7 +139,7 @@ AUTH_PASSWORD_VALIDATORS = [
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
TIME_ZONE = 'Europe/Moscow'
USE_I18N = True
@ -153,3 +155,6 @@ STATIC_ROOT = path.join(BASE_DIR, 'static')
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
CELERY_BROKER_URL = 'redis://localhost:6379/'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/'

4
requirements.txt

@ -12,3 +12,7 @@ soupsieve==2.3.2.post1
sqlparse==0.4.3
urllib3==1.26.13
vk-api==11.9.9
celery==5.3.6
django-celery-beat==2.6.0
redis==5.0.4

Loading…
Cancel
Save