Django queryset show english translations
Question:
This is my Django models.py
:
from django.db import models
class Blog(models.Model):
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.pub_date
class LanguagesCode(models.Model):
code = models.CharField(max_length=5)
def __str__(self):
return self.code
class BlogTranslation(models.Model):
name = models.CharField(max_length=250)
content = models.TextField(blank=True, null=True)
blog_id = models.ForeignKey(Blog, related_name='translations', on_delete=models.CASCADE)
language_code = models.ForeignKey(LanguagesCode, related_name='languages', on_delete=models.DO_NOTHING)
class Meta:
unique_together = ('blog_id', 'language_code')
def __str__(self):
return self.name
I want to show the list of blogs those have english translation, with name in english.
How do I need to write my query to get this data:
[
{
"name": "1st Blog name in english",
"content": "content in english",
"pub_date": "XXX"
},
{
"name": "2nd Blog name in english",
"content": "content in english",
"pub_date": "XXX"
},
]
I use Django 4 with Django Rest Framework. I want my query to start from Blog model.
This is my best try, which doesn’t give me the result I want:
Blog.objects.filter(translations__id = 2)
Answers:
You can use values()
so:
BlogTranslation.objects.filter(language_code__code='en').values('name', 'content', 'blog_id__pub_date')
Then you only need to serialize it to get the data in JSON format.
Edit
To query from Blog
model use Q()
objects so:
from django.db.models import Q
blogs = Blog.objects.filter(
translations__language_code__code='en'
).values(
'translations__name',
'translations__content',
'pub_date'
).distinct()
I continued my research and found the answer that outputs the exact JSON I want and it uses the most efficient SQL among other solutions I tried. Thanks Sunderam for your answer. It helped me to continue my research.
This the SQL it executes:
SELECT "blog_blog"."pub_date",
"blog_blogtranslation"."name" AS "name",
"blog_blogtranslation"."content" AS "content"
FROM "blog_blog"
INNER JOIN "blog_blogtranslation" ON ("blog_blog"."id" = "blog_blogtranslation"."blog_id_id")
WHERE "blog_blogtranslation"."language_code_id" = 2
This is the Django query:
from django.db.models import Prefetch, F
Blog.objects.filter(translations__language_code=2).prefetch_related(
Prefetch('translations', queryset=BlogTranslation.objects.filter(language_code=2))
).values('pub_date').annotate(name=F('translations__name')).annotate(content=F('translations__content'))
This is my Django models.py
:
from django.db import models
class Blog(models.Model):
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.pub_date
class LanguagesCode(models.Model):
code = models.CharField(max_length=5)
def __str__(self):
return self.code
class BlogTranslation(models.Model):
name = models.CharField(max_length=250)
content = models.TextField(blank=True, null=True)
blog_id = models.ForeignKey(Blog, related_name='translations', on_delete=models.CASCADE)
language_code = models.ForeignKey(LanguagesCode, related_name='languages', on_delete=models.DO_NOTHING)
class Meta:
unique_together = ('blog_id', 'language_code')
def __str__(self):
return self.name
I want to show the list of blogs those have english translation, with name in english.
How do I need to write my query to get this data:
[
{
"name": "1st Blog name in english",
"content": "content in english",
"pub_date": "XXX"
},
{
"name": "2nd Blog name in english",
"content": "content in english",
"pub_date": "XXX"
},
]
I use Django 4 with Django Rest Framework. I want my query to start from Blog model.
This is my best try, which doesn’t give me the result I want:
Blog.objects.filter(translations__id = 2)
You can use values()
so:
BlogTranslation.objects.filter(language_code__code='en').values('name', 'content', 'blog_id__pub_date')
Then you only need to serialize it to get the data in JSON format.
Edit
To query from Blog
model use Q()
objects so:
from django.db.models import Q
blogs = Blog.objects.filter(
translations__language_code__code='en'
).values(
'translations__name',
'translations__content',
'pub_date'
).distinct()
I continued my research and found the answer that outputs the exact JSON I want and it uses the most efficient SQL among other solutions I tried. Thanks Sunderam for your answer. It helped me to continue my research.
This the SQL it executes:
SELECT "blog_blog"."pub_date",
"blog_blogtranslation"."name" AS "name",
"blog_blogtranslation"."content" AS "content"
FROM "blog_blog"
INNER JOIN "blog_blogtranslation" ON ("blog_blog"."id" = "blog_blogtranslation"."blog_id_id")
WHERE "blog_blogtranslation"."language_code_id" = 2
This is the Django query:
from django.db.models import Prefetch, F
Blog.objects.filter(translations__language_code=2).prefetch_related(
Prefetch('translations', queryset=BlogTranslation.objects.filter(language_code=2))
).values('pub_date').annotate(name=F('translations__name')).annotate(content=F('translations__content'))