Skip to content

Commit

Permalink
chore: merge beta to main (#3637)
Browse files Browse the repository at this point in the history
* feat: add graphql (#3632)

* feat: add GraphQL support with schema and queries for articles, blogs, and reports

* feat: extend GraphQL schema to include Launch and Event types with new queries for articles and blogs by news site, launch, and event

* refactor: remove logging configuration from settings.py

* feat: add NewsSite type to GraphQL schema and fix typo in LaunchType fields

* feat: implement GraphQL types and queries for Article, Blog, Report, Launch, Event, and NewsSite

* feat: update GraphQL types to use custom filter classes for Article, Blog, and Report

* feat: enhance article and blog queries with ordering by published date

* fix: remove ordering from all_articles query in GraphQL schema

* chore: sync pyproject

* chore: ignore type beceause it's not available

* build: 4.17.0-rc.1

Automatically generated by python-semantic-release

* chore: update harvester to 0.10.0

* fix: update commit message format for semantic release

* build: 4.17.0-rc.2

Automatically generated by python-semantic-release

* chore: remove unused pika-stubs

* feat: generate the label dynamically

* feat(#3630): add django admin dark theme (#3633)

* feat(#3630): django admin dark theme

* fix: update STATIC_ROOT and add STATICFILES_DIRS for improved static file handling

---------

Co-authored-by: Derk Weijers <[email protected]>

* chore: package updates

---------

Co-authored-by: semantic-release <semantic-release>
Co-authored-by: Arnaud Muller <[email protected]>
  • Loading branch information
derkweijers and Nosudrum authored Dec 2, 2024
1 parent eb57250 commit b036b8a
Show file tree
Hide file tree
Showing 21 changed files with 17,431 additions and 166 deletions.
2,247 changes: 2,247 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "snapy"
version = "4"
version = "4.17.0-rc.2"
description = "Spaceflight News API (SNAPI) enables developers to add the latest spaceflight news to their apps."
authors = [{ name = "Derk Weijers", email = "[email protected]" }]
readme = "README.md"
Expand All @@ -26,7 +26,8 @@ dependencies = [
"pyyaml>=6.0.2",
"sentry-sdk>=2.14.0",
"uritemplate>=4.1.1",
"harvester>=0.9.0",
"harvester>=0.10.0",
"graphene-django>=3.2.2",
]

[tool.uv]
Expand All @@ -37,7 +38,6 @@ dev-dependencies = [
"django-filter-stubs>=0.1.3",
"djangorestframework-stubs[compatible-mypy]>=3.14.0,<3.15.0",
"mypy>=1.7.0,<1.8.0",
"pika-stubs>=0.1.3",
"pytest>=8.3.3",
"pytest-codspeed>=2.2.1",
"pytest-cov>=5.0.0",
Expand Down Expand Up @@ -91,7 +91,7 @@ update_changelog_on_bump = false

[tool.semantic_release]
assets = []
commit_message = "{version}\n\nAutomatically generated by python-semantic-release"
commit_message = "build: {version}\n\nAutomatically generated by python-semantic-release"
commit_parser = "angular"
logging_use_named_masks = false
major_on_zero = true
Expand Down
61 changes: 61 additions & 0 deletions src/api/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# type: ignore

from graphene import ObjectType, relay
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField

from api.models import Article, Blog, Event, Launch, NewsSite, Report
from api.views.filters import BaseFilter, DocsFilter


class ArticleType(DjangoObjectType):
class Meta:
model = Article
exclude = ["is_deleted"]
filterset_class = DocsFilter
interfaces = (relay.Node,)


class BlogType(DjangoObjectType):
class Meta:
model = Blog
exclude = ["is_deleted"]
filterset_class = DocsFilter
interfaces = (relay.Node,)


class ReportType(DjangoObjectType):
class Meta:
model = Report
exclude = ["is_deleted"]
filterset_class = BaseFilter
interfaces = (relay.Node,)


class LaunchType(DjangoObjectType):
class Meta:
model = Launch
interfaces = (relay.Node,)


class EventType(DjangoObjectType):
class Meta:
model = Event
interfaces = (relay.Node,)


class NewsSiteType(DjangoObjectType):
class Meta:
model = NewsSite
interfaces = (relay.Node,)


class Query(ObjectType):
article = relay.Node.Field(ArticleType)
all_articles = DjangoFilterConnectionField(ArticleType)

blog = relay.Node.Field(BlogType)
all_blogs = DjangoFilterConnectionField(BlogType)

report = relay.Node.Field(ReportType)
all_reports = DjangoFilterConnectionField(ReportType)
5 changes: 1 addition & 4 deletions src/api/views/articles.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django_filters import rest_framework
from rest_framework import filters, viewsets
from rest_framework import viewsets

from api.models import Article
from api.serializers import ArticleSerializer
Expand All @@ -15,9 +15,6 @@ class ArticleViewSet(viewsets.ReadOnlyModelViewSet): # type: ignore
filter_backends = [
rest_framework.DjangoFilterBackend,
SearchFilter,
filters.OrderingFilter,
]
filterset_class = DocsFilter
search_fields = ["title", "summary", "news_site__name"]
ordering = ["-published_at"]
ordering_fields = ["published_at", "updated_at"]
5 changes: 1 addition & 4 deletions src/api/views/blogs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django_filters import rest_framework
from rest_framework import filters, viewsets
from rest_framework import viewsets

from api.models import Blog
from api.serializers import BlogSerializer
Expand All @@ -13,9 +13,6 @@ class BlogViewSet(viewsets.ReadOnlyModelViewSet): # type: ignore
filter_backends = [
rest_framework.DjangoFilterBackend,
SearchFilter,
filters.OrderingFilter,
]
filterset_class = DocsFilter
search_fields = ["title", "summary", "news_site__name"]
ordering = ["-published_at"]
ordering_fields = ["published_at", "updated_at"]
26 changes: 26 additions & 0 deletions src/api/views/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
FilterSet,
IsoDateTimeFilter,
NumberFilter,
OrderingFilter,
UUIDFilter,
)
from rest_framework import filters
Expand Down Expand Up @@ -98,6 +99,21 @@ def filter_keywords(self, queryset: QuerySet[Any], name: str, value: str) -> Any
return queryset.filter(q)


class OrderingFilterWithLabel(OrderingFilter):
def __init__(self, **kwargs: Any) -> None:
self.fields = kwargs.get("fields")

assert self.fields, "The 'fields' argument is required."

# Itterate over the tupple, generating a string of all first elements, including negative ones.
fields = ", ".join([f"{field[0]}, -{field[0]}" for field in self.fields])

super().__init__(
label=f"Order the result on `{fields}`.",
**kwargs,
)


class BaseFilter(FilterSet):
title_contains = CharFilter(
field_name="title",
Expand Down Expand Up @@ -156,6 +172,16 @@ class BaseFilter(FilterSet):
label="Get all documents updated before a given ISO8601 " "timestamp (excluded).",
)

ordering = OrderingFilterWithLabel(
fields=(
(
"published_at",
"published_at",
),
("updated_at", "updated_at"),
),
)


class DocsFilter(BaseFilter):
launch = UUIDInFilter(
Expand Down
5 changes: 1 addition & 4 deletions src/api/views/reports.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django_filters import rest_framework
from rest_framework import filters, viewsets
from rest_framework import viewsets

from api import serializers
from api.models.report import Report
Expand All @@ -14,8 +14,5 @@ class ReportViewSet(viewsets.ReadOnlyModelViewSet): # type: ignore
filter_backends = [
rest_framework.DjangoFilterBackend,
SearchFilter,
filters.OrderingFilter,
]
search_fields = ["title", "summary", "news_site__name"]
ordering = ["-published_at"]
ordering_fields = ["published_at", "updated_at"]
12 changes: 12 additions & 0 deletions src/snapy/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# type: ignore

from graphene import ObjectType, Schema

from api.schema import Query as ApiQuery


class Query(ApiQuery, ObjectType):
pass


schema = Schema(query=Query)
21 changes: 8 additions & 13 deletions src/snapy/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"health_check",
"health_check.db",
"health_check.contrib.s3boto3_storage",
"graphene_django",
]

MIDDLEWARE = [
Expand Down Expand Up @@ -110,6 +111,8 @@
},
]

JET_DEFAULT_THEME = "dark"

WSGI_APPLICATION = "snapy.wsgi.application"

# Database
Expand Down Expand Up @@ -165,7 +168,9 @@
STATICFILES_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
else:
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STATIC_ROOT = BASE_DIR.joinpath("staticfiles")

STATICFILES_DIRS = [BASE_DIR.joinpath("static")]

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
Expand Down Expand Up @@ -208,16 +213,6 @@
},
}

LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {
"class": "logging.StreamHandler",
},
},
"root": {
"handlers": ["console"],
"level": "INFO",
},
GRAPHENE = {
"SCHEMA": "snapy.schema.schema",
}
3 changes: 3 additions & 0 deletions src/snapy/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@

from django.contrib import admin
from django.urls import include, re_path
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView # type: ignore

urlpatterns = [
re_path(r"^v4/jet/", include("jet.urls", "jet")), # Django JET URLS
re_path(r"^v4/jet/dashboard/", include("jet.dashboard.urls", "jet-dashboard")), # Django JET dashboard URLS
re_path(r"^v4/admin/", admin.site.urls),
re_path(r"^v4/", include(("api.urls", "api"), namespace="v4")),
re_path(r"^v4/graphql/", csrf_exempt(GraphQLView.as_view(graphiql=True))),
# Non v4 URLs
re_path(r"health/", include("health_check.urls")),
]
3 changes: 3 additions & 0 deletions src/static/jet/css/themes/dark/_variables.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/*
* These theme uses default variables at ../_variables.scss
*/
Loading

0 comments on commit b036b8a

Please sign in to comment.