Skip to content

Commit 832c62e

Browse files
feat: format+has_errata, drop see_also for red API (#10392)
* fix: has_errata field for red API * chore: explanatory comment * feat: accurate format list for red API * refactor: specify blob names in API * chore: remove see_also field * fix: finish removing see_also field
1 parent 4a024d9 commit 832c62e

File tree

3 files changed

+63
-15
lines changed

3 files changed

+63
-15
lines changed

ietf/doc/api.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
# Copyright The IETF Trust 2024-2026, All Rights Reserved
22
"""Doc API implementations"""
33

4-
from django.db.models import OuterRef, Subquery, Prefetch, Value, JSONField, QuerySet
4+
from django.db.models import (
5+
BooleanField,
6+
Count,
7+
JSONField,
8+
OuterRef,
9+
Prefetch,
10+
Q,
11+
QuerySet,
12+
Subquery,
13+
Value,
14+
)
515
from django.db.models.functions import TruncDate
616
from django_filters import rest_framework as filters
717
from rest_framework import filters as drf_filters
@@ -133,11 +143,18 @@ def augment_rfc_queryset(queryset: QuerySet[Document]):
133143
)
134144
.annotate(published=TruncDate("published_datetime", tzinfo=RPC_TZINFO))
135145
.annotate(
136-
# TODO implement these fake fields for real
137-
see_also=Value([], output_field=JSONField()),
138-
formats=Value(["txt", "xml"], output_field=JSONField()),
146+
# Count of "verified-errata" tags will be 1 or 0, convert to Boolean
147+
has_errata=Count(
148+
"tags",
149+
filter=Q(
150+
tags__slug="verified-errata",
151+
),
152+
output_field=BooleanField(),
153+
)
154+
)
155+
.annotate(
156+
# TODO implement this fake field for real
139157
keywords=Value(["keyword"], output_field=JSONField()),
140-
errata=Value([], output_field=JSONField()),
141158
)
142159
)
143160

ietf/doc/models.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,24 @@ def action_holders_enabled(self):
12841284
iesg_state = self.get_state('draft-iesg')
12851285
return iesg_state and iesg_state.slug != 'idexists'
12861286

1287+
def formats(self):
1288+
"""List of file formats available
1289+
1290+
Only implemented for RFCs. Relies on StoredObject.
1291+
"""
1292+
if self.type_id != "rfc":
1293+
raise RuntimeError("Only allowed for type=rfc")
1294+
return [
1295+
{
1296+
"fmt": Path(object_name).parts[0],
1297+
"name": object_name,
1298+
}
1299+
for object_name in StoredObject.objects.filter(
1300+
store="rfc", doc_name=self.name, doc_rev=self.rev
1301+
).values_list("name", flat=True)
1302+
]
1303+
1304+
12871305
class DocumentURL(models.Model):
12881306
doc = ForeignKey(Document)
12891307
tag = ForeignKey(DocUrlTagName)

ietf/doc/serializers.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
class RfcAuthorSerializer(serializers.ModelSerializer):
1818
"""Serializer for an RfcAuthor / DocumentAuthor in a response"""
19+
1920
datatracker_person_path = serializers.URLField(
2021
source="person.get_absolute_url",
2122
required=False,
@@ -36,7 +37,7 @@ class Meta:
3637

3738
def to_representation(self, instance):
3839
"""instance -> primitive data types
39-
40+
4041
Translates a DocumentAuthor into an equivalent RfcAuthor we can use the same
4142
serializer for either type.
4243
"""
@@ -87,7 +88,15 @@ class DocIdentifierSerializer(serializers.Serializer):
8788

8889

8990
type RfcStatusSlugT = Literal[
90-
"std", "ps", "ds", "bcp", "inf", "exp", "hist", "unkn", "not-issued",
91+
"std",
92+
"ps",
93+
"ds",
94+
"bcp",
95+
"inf",
96+
"exp",
97+
"hist",
98+
"unkn",
99+
"not-issued",
91100
]
92101

93102

@@ -188,11 +197,16 @@ class ContainingSubseriesSerializer(serializers.Serializer):
188197
type = serializers.CharField(source="source.type_id")
189198

190199

200+
class RfcFormatSerializer(serializers.Serializer):
201+
RFC_FORMATS = ("xml", "txt", "html", "pdf", "ps", "json", "notprepped")
202+
203+
fmt = serializers.ChoiceField(choices=RFC_FORMATS)
204+
name = serializers.CharField(help_text="Name of blob in the blob store")
205+
206+
191207
class RfcMetadataSerializer(serializers.ModelSerializer):
192208
"""Serialize metadata of an RFC"""
193209

194-
RFC_FORMATS = ("xml", "txt", "html", "htmlized", "pdf", "ps")
195-
196210
number = serializers.IntegerField(source="rfc_number")
197211
published = serializers.DateField()
198212
status = RfcStatusSerializer(source="*")
@@ -207,10 +221,11 @@ class RfcMetadataSerializer(serializers.ModelSerializer):
207221
updates = RelatedRfcSerializer(many=True, read_only=True)
208222
updated_by = ReverseRelatedRfcSerializer(many=True, read_only=True)
209223
subseries = ContainingSubseriesSerializer(many=True, read_only=True)
210-
see_also = serializers.ListField(child=serializers.CharField(), read_only=True)
211-
formats = serializers.MultipleChoiceField(choices=RFC_FORMATS)
224+
formats = RfcFormatSerializer(
225+
many=True, read_only=True, help_text="Available formats"
226+
)
212227
keywords = serializers.ListField(child=serializers.CharField(), read_only=True)
213-
errata = serializers.ListField(child=serializers.CharField(), read_only=True)
228+
has_errata = serializers.BooleanField(read_only=True)
214229

215230
class Meta:
216231
model = Document
@@ -230,15 +245,13 @@ class Meta:
230245
"updates",
231246
"updated_by",
232247
"subseries",
233-
"see_also",
234248
"draft",
235249
"abstract",
236250
"formats",
237251
"keywords",
238-
"errata",
252+
"has_errata",
239253
]
240254

241-
242255
@extend_schema_field(RfcAuthorSerializer(many=True))
243256
def get_authors(self, doc: Document):
244257
# If doc has any RfcAuthors, use those, otherwise fall back to DocumentAuthors

0 commit comments

Comments
 (0)