diff --git a/backend/api/blog/__init__.py b/backend/api/blog/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/backend/api/blog/schema.py b/backend/api/blog/schema.py deleted file mode 100644 index e5928721f8..0000000000 --- a/backend/api/blog/schema.py +++ /dev/null @@ -1,52 +0,0 @@ -from api.context import Info -import strawberry - -from blog.models import Post - -from .types import BlogPostAuthor -from .types import Post as PostType - - -@strawberry.type -class BlogQuery: - @strawberry.field - def blog_posts(self, info: Info) -> list[PostType]: - return [ - PostType( - id=post.id, - author=BlogPostAuthor( - id=post.author_id, full_name=post.author.full_name - ), - title=post.title, - slug=post.slug, - excerpt=post.excerpt, - content=post.content, - published=post.published, - image=( - info.context.request.build_absolute_uri(post.image.url) - if post.image - else None - ), - ) - for post in Post.published_posts.all() - ] - - @strawberry.field - def blog_post(self, info: Info, slug: str) -> PostType | None: - post = Post.published_posts.by_slug(slug).first() - - if not post: - return None - - return PostType( - id=post.id, - author=BlogPostAuthor(id=post.author_id, full_name=post.author.full_name), - title=post.title, - slug=post.slug, - excerpt=post.excerpt, - content=post.content, - published=post.published, - image=info.context.request.build_absolute_uri(post.image.url) - if post.image - else None, - ) diff --git a/backend/api/blog/types.py b/backend/api/blog/types.py deleted file mode 100644 index 3e2979635f..0000000000 --- a/backend/api/blog/types.py +++ /dev/null @@ -1,44 +0,0 @@ -from datetime import datetime -from typing import Optional - -import strawberry - -from ..helpers.i18n import make_localized_resolver - - -@strawberry.type -class BlogPostAuthor: - id: strawberry.ID - full_name: str - - -@strawberry.type -class Post: - id: strawberry.ID - author: BlogPostAuthor - title: str = strawberry.field(resolver=make_localized_resolver("title")) - slug: str = strawberry.field(resolver=make_localized_resolver("slug")) - excerpt: str = strawberry.field(resolver=make_localized_resolver("excerpt")) - content: str = strawberry.field(resolver=make_localized_resolver("content")) - image: Optional[str] - published: datetime - - def __init__( - self, - id: strawberry.ID, - author: BlogPostAuthor, - title: str, - slug: str, - excerpt: str, - content: str, - published: datetime, - image: Optional[str], - ) -> None: - self.id = id - self.author = author - self.title = title - self.slug = slug - self.excerpt = excerpt - self.content = content - self.published = published - self.image = image diff --git a/backend/api/schema.py b/backend/api/schema.py index a545c71c27..4491a7020b 100644 --- a/backend/api/schema.py +++ b/backend/api/schema.py @@ -3,7 +3,6 @@ from api.participants.mutations import ParticipantMutations from .users.mutations import UsersMutations from .files_upload.schema import FilesUploadMutation -from .blog.schema import BlogQuery from .checklist.query import ChecklistQuery from .conferences.schema import ConferenceQuery from .countries.schema import CountryQuery @@ -33,7 +32,6 @@ @strawberry.type class Query( ConferenceQuery, - BlogQuery, SubmissionsQuery, PagesQuery, CountryQuery, diff --git a/backend/api/tests/schema/test_blog.py b/backend/api/tests/schema/test_blog.py deleted file mode 100644 index b827edfd43..0000000000 --- a/backend/api/tests/schema/test_blog.py +++ /dev/null @@ -1,152 +0,0 @@ -from datetime import timedelta - -from django.utils import timezone -from pytest import mark - -from helpers.tests import get_image_url_from_request -from i18n.strings import LazyI18nString -from blog.tests.factories import PostFactory - - -def _query_blog_posts(client): - return client.query( - """ - query { - blogPosts { - id - title - slug - excerpt - content - published - image - author { - id - } - } - } - """ - ) - - -@mark.django_db -def test_query_blog_posts( - rf, - graphql_client, -): - past_post = PostFactory(published=timezone.now() - timedelta(days=1), image=None) - present_post = PostFactory() - - request = rf.get("/") - - PostFactory(published=timezone.now() + timedelta(days=1)) - - resp = _query_blog_posts(graphql_client) - - assert len(resp["data"]["blogPosts"]) == 2 - - assert { - "id": str(past_post.id), - "title": str(past_post.title), - "slug": str(past_post.slug), - "excerpt": str(past_post.excerpt), - "content": str(past_post.content), - "published": past_post.published.isoformat(), - "image": get_image_url_from_request(request, past_post.image), - "author": {"id": str(past_post.author_id)}, - } == resp["data"]["blogPosts"][1] - - assert { - "id": str(present_post.id), - "title": str(present_post.title), - "slug": str(present_post.slug), - "excerpt": str(present_post.excerpt), - "content": str(present_post.content), - "published": present_post.published.isoformat(), - "image": get_image_url_from_request(request, present_post.image), - "author": { - "id": str(present_post.author_id), - }, - } == resp["data"]["blogPosts"][0] - - -@mark.django_db -def test_query_single_post( - rf, - graphql_client, -): - request = rf.get("/") - post = PostFactory( - slug=LazyI18nString({"en": "demo", "it": "esempio"}), - published=timezone.now() - timedelta(days=1), - image=None, - ) - - resp = graphql_client.query( - """query { - blogPost(slug: "demo") { - id - title - slug - excerpt - content - published - image - author { - id - } - } - } """ - ) - - assert { - "id": str(post.id), - "title": str(post.title), - "slug": str(post.slug), - "excerpt": str(post.excerpt), - "content": str(post.content), - "published": post.published.isoformat(), - "image": get_image_url_from_request(request, post.image), - "author": {"id": str(post.author_id)}, - } == resp["data"]["blogPost"] - - resp = graphql_client.query( - """query { - blogPost(slug: "donut") { - id - } - } """ - ) - - assert resp["data"]["blogPost"] is None - - -@mark.django_db -def test_passing_language(graphql_client): - PostFactory( - title=LazyI18nString({"en": "this is a test", "it": "questa è una prova"}), - slug=LazyI18nString({"en": "slug", "it": "lumaca"}), - content=LazyI18nString({"en": "content", "it": "contenuto"}), - excerpt=LazyI18nString({"en": "excerpt", "it": "sommario"}), - published=timezone.now() - timedelta(days=1), - image=None, - ) - - resp = graphql_client.query( - """query { - blogPost(slug: "slug") { - title(language: "it") - slug(language: "it") - content(language: "it") - excerpt(language: "it") - } - } """ - ) - - assert not resp.get("errors") - assert resp["data"]["blogPost"] == { - "title": "questa è una prova", - "slug": "lumaca", - "content": "contenuto", - "excerpt": "sommario", - } diff --git a/backend/blog/__init__.py b/backend/blog/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/backend/blog/admin.py b/backend/blog/admin.py deleted file mode 100644 index cea6be8437..0000000000 --- a/backend/blog/admin.py +++ /dev/null @@ -1,32 +0,0 @@ -from django import forms -from django.contrib import admin - -from .models import Post - - -class PostAdminForm(forms.ModelForm): - class Meta: - model = Post - fields = [ - "author", - "title", - "slug", - "content", - "excerpt", - "published", - "image", - ] - - -@admin.register(Post) -class PostAdmin(admin.ModelAdmin): - form = PostAdminForm - list_display = ("title", "published", "author_display_name") - user_fk = "author_id" - autocomplete_fields = ("author",) - - @admin.display( - description="Author", - ) - def author_display_name(self, obj): - return obj.author.display_name diff --git a/backend/blog/apps.py b/backend/blog/apps.py deleted file mode 100644 index 10038974b1..0000000000 --- a/backend/blog/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class BlogConfig(AppConfig): - name = "blog" diff --git a/backend/blog/migrations/0001_initial.py b/backend/blog/migrations/0001_initial.py deleted file mode 100644 index 5d7830e93a..0000000000 --- a/backend/blog/migrations/0001_initial.py +++ /dev/null @@ -1,37 +0,0 @@ -# Generated by Django 2.2.3 on 2019-07-18 18:43 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import django.utils.timezone -import model_utils.fields - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Post', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('title', models.CharField(max_length=200, verbose_name='title')), - ('slug', models.SlugField(blank=True, max_length=200, unique=True, verbose_name='slug')), - ('excerpt', models.TextField(null=True, verbose_name='excerpt')), - ('content', models.TextField(null=True, verbose_name='content')), - ('published', models.DateTimeField(default=django.utils.timezone.now, verbose_name='published')), - ('image', models.ImageField(blank=True, null=True, upload_to='blog', verbose_name='image')), - ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'ordering': ['-published'], - }, - ), - ] diff --git a/backend/blog/migrations/0002_auto_20190809_2128.py b/backend/blog/migrations/0002_auto_20190809_2128.py deleted file mode 100644 index ec6122311a..0000000000 --- a/backend/blog/migrations/0002_auto_20190809_2128.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.4 on 2019-08-09 21:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='post', - name='content', - field=models.TextField(blank=True, default='', verbose_name='content'), - ), - migrations.AlterField( - model_name='post', - name='excerpt', - field=models.TextField(blank=True, default='', verbose_name='excerpt'), - ), - ] diff --git a/backend/blog/migrations/0003_auto_20191130_0913.py b/backend/blog/migrations/0003_auto_20191130_0913.py deleted file mode 100644 index e1377e3794..0000000000 --- a/backend/blog/migrations/0003_auto_20191130_0913.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.2.7 on 2019-11-30 09:13 - -from django.db import migrations -import i18n.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0002_auto_20190809_2128'), - ] - - operations = [ - migrations.AlterField( - model_name='post', - name='content', - field=i18n.fields.I18nTextField(blank=True, verbose_name='content'), - ), - migrations.AlterField( - model_name='post', - name='excerpt', - field=i18n.fields.I18nTextField(verbose_name='excerpt'), - ), - migrations.AlterField( - model_name='post', - name='slug', - field=i18n.fields.I18nCharField(blank=True, max_length=200, verbose_name='slug'), - ), - migrations.AlterField( - model_name='post', - name='title', - field=i18n.fields.I18nCharField(max_length=200, verbose_name='title'), - ), - ] diff --git a/backend/blog/migrations/0004_post_author_fk.py b/backend/blog/migrations/0004_post_author_fk.py deleted file mode 100644 index daa36fbddb..0000000000 --- a/backend/blog/migrations/0004_post_author_fk.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.1.4 on 2021-05-02 10:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0003_auto_20191130_0913'), - ] - - operations = [ - migrations.SeparateDatabaseAndState( - database_operations=[ - migrations.AlterField( - model_name='post', - name='author', - field=models.ForeignKey('users.User', db_constraint=False, db_index=True, null=False, on_delete=models.CASCADE) - ), - ], - state_operations=[ - migrations.RemoveField( - model_name='post', - name='author', - ), - migrations.AddField( - model_name='post', - name='author_id', - field=models.IntegerField(verbose_name='author'), - ), - ], - ), - ] diff --git a/backend/blog/migrations/0005_remove_post_author_id_post_author.py b/backend/blog/migrations/0005_remove_post_author_id_post_author.py deleted file mode 100644 index a9a51e1de3..0000000000 --- a/backend/blog/migrations/0005_remove_post_author_id_post_author.py +++ /dev/null @@ -1,52 +0,0 @@ -# Generated by Django 4.2.3 on 2023-10-01 14:02 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ("blog", "0004_post_author_fk"), - ] - - operations = [ - migrations.SeparateDatabaseAndState( - database_operations=[ - migrations.RunSQL( - sql="DROP INDEX IF EXISTS blog_post_author_id_dd7a8485;", - reverse_sql="CREATE INDEX blog_post_author_id_dd7a8485 ON blog_post USING btree (author_id);", - ), - migrations.AlterField( - model_name="post", - name="author_id", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="+", - to=settings.AUTH_USER_MODEL, - verbose_name="author", - db_column="author_id", - ), - ), - ], - state_operations=[ - migrations.RemoveField( - model_name="post", - name="author_id", - ), - migrations.AddField( - model_name="post", - name="author", - field=models.ForeignKey( - default=None, - on_delete=django.db.models.deletion.CASCADE, - related_name="+", - to=settings.AUTH_USER_MODEL, - verbose_name="author", - ), - preserve_default=False, - ), - ], - ) - ] diff --git a/backend/blog/migrations/__init__.py b/backend/blog/migrations/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/backend/blog/models.py b/backend/blog/models.py deleted file mode 100644 index a4158195d4..0000000000 --- a/backend/blog/models.py +++ /dev/null @@ -1,58 +0,0 @@ -from copy import copy - -from django.conf import settings -from django.db import models -from django.db.models import Q -from django.utils import timezone -from django.utils.text import slugify -from django.utils.translation import gettext_lazy as _ -from model_utils.models import TimeStampedModel - -from i18n.fields import I18nCharField, I18nTextField - - -class PostManager(models.Manager): - def get_queryset(self): - return super().get_queryset().filter(published__lte=timezone.now()) - - def by_slug(self, slug): - filters = Q() - - for lang, __ in settings.LANGUAGES: - filters |= Q(**{f"slug__{lang}": slug}) - - return self.get_queryset().filter(filters) - - -class Post(TimeStampedModel): - author = models.ForeignKey( - "users.User", - on_delete=models.CASCADE, - null=False, - blank=False, - verbose_name=_("author"), - related_name="+", - ) - - title = I18nCharField(_("title"), max_length=200) - slug = I18nCharField(_("slug"), max_length=200, blank=True) - content = I18nTextField(_("content"), blank=True) - excerpt = I18nTextField(_("excerpt"), blank=False) - published = models.DateTimeField(_("published"), default=timezone.now) - image = models.ImageField(_("image"), null=True, blank=True, upload_to="blog") - - objects = models.Manager() - published_posts = PostManager() - - def __str__(self): - return str(self.title) - - def save(self, *args, **kwargs): - if not self.slug: - self.slug = copy(self.title) - self.slug.map(slugify) - - super().save(*args, **kwargs) - - class Meta: - ordering = ["-published"] diff --git a/backend/blog/tests/__init__.py b/backend/blog/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/backend/blog/tests/factories.py b/backend/blog/tests/factories.py deleted file mode 100644 index 0c3c4c5fd4..0000000000 --- a/backend/blog/tests/factories.py +++ /dev/null @@ -1,21 +0,0 @@ -import factory -import factory.fuzzy -from django.utils import timezone -from factory.django import DjangoModelFactory - -from blog.models import Post -from i18n.tests.factories import LanguageFactory -from users.tests.factories import UserFactory - - -class PostFactory(DjangoModelFactory): - author = factory.SubFactory(UserFactory) - title = LanguageFactory("sentence") - slug = LanguageFactory("slug") - excerpt = LanguageFactory("sentence") - content = LanguageFactory("sentence") - published = timezone.now() - image = factory.django.ImageField() - - class Meta: - model = Post diff --git a/backend/blog/tests/test_models.py b/backend/blog/tests/test_models.py deleted file mode 100644 index 9435551053..0000000000 --- a/backend/blog/tests/test_models.py +++ /dev/null @@ -1,8 +0,0 @@ -from blog.tests.factories import PostFactory -import pytest - - -@pytest.mark.django_db -def test_automatic_slug(): - post = PostFactory(slug=None) - assert post.slug diff --git a/backend/demodata/blog.json b/backend/demodata/blog.json deleted file mode 100644 index d7bdb468a3..0000000000 --- a/backend/demodata/blog.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "model": "blog.post", - "pk": 1, - "fields": { - "created": "2019-09-01T15:18:46.795Z", - "modified": "2019-09-01T15:18:46.795Z", - "author_id": 1, - "title": { - "en": "Example title", - "it": "Titolo d'esempio" - }, - "slug": { - "en": "example", - "it": "esempio" - }, - "excerpt": { - "en": "example", - "it": "esempio" - }, - "content": { - "en": "example", - "it": "esempio" - }, - "published": "2019-09-01T15:18:18Z", - "image": "" - } - } -] diff --git a/backend/pycon/settings/base.py b/backend/pycon/settings/base.py index 2821bf9fa3..883498df30 100644 --- a/backend/pycon/settings/base.py +++ b/backend/pycon/settings/base.py @@ -95,7 +95,6 @@ "languages.apps.LanguagesConfig", "submissions.apps.SubmissionsConfig", "voting.apps.VotingConfig", - "blog.apps.BlogConfig", "pages.apps.PagesConfig", "sponsors.apps.SponsorsConfig", "cms.apps.CMSConfig", diff --git a/backend/pyproject.toml b/backend/pyproject.toml index f85176bd12..2f650c2b3b 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -28,7 +28,6 @@ known-first-party = [ "cms", "sponsors", "pages", - "blog", "voting", "submissions", "languages",