I understand that my question is repeated often, but i'm stuck with this. I want to make simple api with DRF. I have two models:
models.py
class Rubrics(models.Model):
id = models.AutoField(primary_key=True)
rubric = models.CharField(max_length=255, blank=True, null=True)
class Books(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255, blank=True, null=True)
author = models.CharField(max_length=255, blank=True, null=True)
date = models.CharField(max_length=255, blank=True, null=True)
rubrics = models.ForeignKey('Rubrics', on_delete=models.DO_NOTHING, related_name='books', blank=True, null=True)
I'd like to view serialized result like this:
[
rubric1: [
{
title: "title1",
author:"author1"
},
book_obj2,
so on
],
rubric2: [
book_obj4,
book_obj5
]
]
my views.py:
class BooksByRubricView(APIView):
"""List of books by rubrics"""
def get(self, request):
last_date = Books.objects.latest("date").date
books_last = Books.objects.filter(date=last_date)
serializer = RubricsSerializer(books_last, many=True)
return Response(serializer.data)
I try a lot of examples in this theme,
sorry this garbage
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Books
#fields = ("title",)
exclude = ()
class RubricsSerializer(serializers.ModelSerializer):
rubrics = BookSerializer(read_only=True)
class Meta:
model = Rubrics
fields = ("rubrics",)
#exclude = ()
"""
class RubricSerializer(serializers.ModelSerializer):
#rubrics = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
#books = RecursiveSerializer(many=True)
#print(books)
rubrics = RubricSerializer(read_only=True)
#books = BooksListSerializer(many=True)
class Meta:
model = Books
fields = ("title", "rubrics",)
#fields = ['rubric', 'rubrics']
#fields = ['books', 'rubrics']
"""
but maybe i don't understand principles of reverse relationships and serializing in DRF. Please, tell me WAIDW. Thanks.
UPD. I want to operate only on specified set of data (for example, work with last uploaded books), not on whole table Books. So i want to view only rubrics, that are in this set, not all rubrics from table Rubrics. Yes, books have only one rubric id in specified field, and rubric has one-to-many relationship to books. Well, that's json i want to see (of course, all characters appearing in this work, are fictitious. Any resemblance to real persons, living or dead, is purely coincidental.):
{
"rubric1": [{
"author": "Marley W. Watkins",
"title": "A Step-By-Step Guide to Exploratory Factor Analysis with Stata"
}, {
"author": "Robert E. Davis",
"title": "Auditing Information and Cyber Security Governance; A Controls-Based Approach"
}, {
"author": "Gerhard X. Ritter, Gonzalo Urcid",
"title": "Introduction to Lattice Algebra: With Applications in AI, Pattern Recognition, Image Analysis, and Biomimetic Neural Networks"
}],
"rubric2": [{
"author": "Richard Cross and JT Paasch",
"title": "The Routledge Companion to Medieval Philosophy"
}, {
"author": "Nicholas Allott (editor), Terje Lohndal (editor), Georges Rey (editor)",
"title": "A Companion to Chomsky"
}, {
"author": "Olakunle George",
"title": "A Companion to African Literatures"
}, {
"author": "Tim Byrnes, Ebubechukwu O. Ilo-Okeke",
"title": "Quantum Atom Optics: Theory and Applications to Quantum Technology"
}],
"rubric3": [{
"author": "Hiroyoshi Naito",
"title": "Organic Semiconductors for Optoelectronics"
}, {
"author": "Bassem R. Mahafza, Scott C. Winton",
"title": "Handbook of Radar Signal Analysis"
}, {
"author": "Sean McManus, Mike Cook",
"title": "Raspberry Pi For Dummies, 4th Edition"
}]
}
i realize it in "plain" django:
class BooksByRubricView(APIView):
"""List of books by rubrics"""
def get(self, request):
last_date = Books.objects.using('books').latest("date").date
books_last = Books.objects.using('books').filter(date=last_date)
categories = []
res_dict = {}
for item in books_last:
categories.append(item.rubrics_id)
categories = set(categories)
for item in categories:
temp_list = []
temp_qs = books_last.filter(rubrics_id=item)
for i in temp_qs:
temp_list.append({"author": i["author"], "title": i["title"]})
res_dict["rubric"+str(item)]=list(temp_list)
# res = json.dumps(res_dict)
return JsonResponse(res_dict, safe=False, json_dumps_params={'ensure_ascii': False})
can i realize it with drf serializators or simplest way is not f*cking any brains and return json as above?
UPD2. Well, after some magic with serializers and generic.APIView i've got result not exactly expected, but very closest to that. Example (of course, all characters appearing in this work, are fictitious. Any resemblance to real persons, living or dead, is purely coincidental)
views.py
class BooksByRubricView2(generics.ListAPIView):
"""Books grouped by rubrics"""
serializer_class = RubricsSerializer2
queryset = Rubrics.objects.all()
#OR without generic
class BooksByRubricView3(APIView):
def get(self, request):
r = Rubrics.objects.all()
serializer=RubricsSerializer2(r,many=True)
return Response(serializer.data)
serializers.py
class FilteredListSerializer(serializers.ListSerializer):
"""Serializer to filter Book table, look for latest date for every rubric"""
def to_representation(self, data):
latest_data = data.latest("date").date
data = data.filter(date=latest_data)
return super(FilteredListSerializer, self).to_representation(data)
class BookSerializer2(serializers.ModelSerializer):
class Meta:
model = Books
list_serializer_class = FilteredListSerializer
fields = (
"title",
"author",
"date")
class RubricsSerializer2(serializers.ModelSerializer):
books = BookSerializer2(many=True, read_only=True)
class Meta:
model = Rubrics
fields = ("rubric", "books",)
result:
[
{
"rubric": "Computers",
"books": [
{
"title": "A Step-By-Step Guide to Exploratory Factor Analysis with Stata",
"author": "Marley W. Watkins",
"date": "2021-08-08"
},
{
"title": "Auditing Information and Cyber Security Governance; A Controls-Based Approach",
"author": "Robert E. Davis",
"date": "2021-08-08"
}
]
},
{
"rubric": "Education",
"books": [
{
"title": "The Routledge Companion to Medieval Philosophy",
"author": "Richard Cross and JT Paasch",
"date": "2021-08-08"
}
]
},
so on
}
it's a dirty way because every Rubric from table Rubrics creates its own query to table Books and each Rubric has its own latest date. But DRF filtering will be next step... =)
Thanks all folks, "i'll be back"
