Here are simplified model definitions
class Resource(models.Model):
name = models.CharField(max_length=100, unique=True)
class Location(models.Model):
name = models.CharField(max_length=100, unique=True)
resources = models.ManyToManyField(Resource)
And I want to know for one type of Resource
, the existence on each Location
. So the json data I want is like
[
{
"id": 1,
"name": "loaction_A",
"resource": true
},
{
"id": 2
"name": "location_B",
"resource": false
},
...
]
I tried following view function but obviously got wrong results.
def resource_view(request, res_id):
res = get_object_or_404(Resource, pk=res_id)
locations = Location.objects.values('id', 'name')\
.annotate(resource=Q(resources=res))
return JsonResponce({'locations': list(locations)})
I know I need something like below (in SQL)
select
app_location.*,
1 in (
select resource_id
from app_location_resources
where location_id = app_location.id
) as resource
from app_location
How should I construct the queryset?
A slightly more efficient way could be:
from django.db.models import Exists, OuterRef
locations = Location.objects.annotate(
resource=Exists(
Location.resources.through.objects.filter(
location_id=OuterRef('pk'), resource_id=res_id
)
)
)
I would however advise to user a proper serializer like in the Django REST framework and perhaps use the Django REST framework: the serializer can then work bi-directional and for example makes it possible to render data in a comma-separated value (.csv
) format.