I need help with writing proper queryset in Django View. I have Post model with created_at (datetime field). I want to group it by date and return in a specific format.
models.py
class Post(TrackableDate):
title = models.CharField(max_length=255)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
views.py
class PostViewSet(mixins.ListModelMixin,
viewsets.GenericViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
serializers.py
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
The usual response looks like:
[
{
"id": 1,
"text": "ok",
"created_at": "2012-12-12T12:30:00"
},
{
"id": 2,
"text": "ok",
"created_at": "2012-12-12T12:30:00"
},
{
"id": 3,
"text": "ok",
"created_at": "2012-12-13T12:30:00"
}
]
How to group and return like that?
{
"2012-12-12": [
{
"id": 1,
"text": "ok",
"created_at": "2012-12-12T12:30:00"
},
{
"id": 2,
"text": "ok",
"created_at": "2012-12-12T12:30:00"
}
],
"2012-12-13": [
{
"id": 3,
"text": "ok",
"created_at": "2012-12-13T12:30:00"
}
]
}
I tried to do
Post.objects.extra(select={'created_at': 'date(created_at)'}).values('created_at').annotate(available=Count('created_at'))
But it returns
<QuerySet [{'created_at': '2020-07-04', 'available': 7}, {'created_at': '2020-07-09', 'available': 2}]>
This is a helper function, you can accomplish your results like this, it may be a better solution. This is the one that I came up with
def group_by_date(mydata):
new_data = {}
for element in mydata:
v = element['created_at'].split('T')[0]
if v not in new_data.keys():
new_data[v] = []
new_data[v].append(element)
return new_data
You can override the get function of your API and rework the output
and override return Response(group_by_date(serializer.data), HTTP_200_OK)
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed last year.
Improve this question
Since I am new to this DRF I am facing some difficulties creating this JSON. I have created an API endpoint and the output of that API endpoint is like this now as shown below
"meta": {
"limit": 1,
"page_count": 1,
"total_count": 1
},
"results": {
"id": 1234567,
"curriculum": {
"ES Math": [
{
"grade_level": "ES",
"subject": "Math",
"subject_abbr": "Math",
"product_id": 438,
"product_title": "Test1",
"ratings": [
{
"source": "A",
"report_url": "********",
"Org1_rating": [
{
"name": "green_alignment_ratings",
"value": 12,
"label": "Meet Expectations",
"label_color": "Green"
},
{
"name": "green_usability_ratings",
"value": 12,
"label": "Meet Expectations",
"label_color": "Green"
}
],
"Org2_rating": [
{
"name": "Overall",
"value": null,
"label": "Tier 1: Exemplifies Quality",
"label_color": null
}
]
}
]
},
{
"grade_level": "ES",
"subject": "Math",
"subject_abbr": "Math",
"product_id": 2085,
"product_title": "Test2",
"ratings": [
{
"source": "A",
"report_url": "********",
"Org1_rating": [
{
"name": "green_alignment_ratings",
"value": 12,
"label": "Meet Expectations",
"label_color": "Green"
},
{
"name": "green_usability_ratings",
"value": 12,
"label": "Meet Expectations",
"label_color": "Green"
}
],
"Org_rating2": "null"
}
]
}
]
}
}
}
But I want the output to be in this format below
{
"meta": {
"limit": 1,
"page_count": 1,
"total_count": 1
},
"results": {
"id": 1234567,
"curriculum": {
"ES Math": [
{
"grade_level": "ES",
"subject": "Math",
"subject_abbr": "Math",
"product_id": 438,
"product_title": "Test1",
"ratings": [
{
"review_org": "Org1",
"review_url": "url",
"review_items": [
{
"name": "green_alignment_ratings",
"value": 14,
"label": "Meets Expectations",
"label_color": "Green"
},
{
"name": "green_usability_ratings",
"value": 34,
"label": "Green",
"label_color": 38
}
]
},
{
"review_org": "Org2",
"review_url": "url",
"review_items": [
{
"name": "Overall",
"value": null,
"Label": "Tier I, Exemplifies quality",
"scale": null
}
]
}
]
},
{
"grade_level": "ES",
"subject": "Math",
"subject_abbr": "Math",
"product_id": 2085,
"product_title": "Test2",
"ratings": [
{
"review_org": "Org1",
"review_url": "url",
"review_items": [
{
"name":"green_alignment_ratings",
"value": 14,
"label": "Meets Expectations",
"label_color": "Green"
},
{
"name":"green_usability_ratings",
"value": 34,
"label": "Meets Expectations",
"label_color": "Green"
}
]
},
{
"review_org": "Org2",
"review_url": "url",
"review_items": []
}
]
}
]
}
}
}
And I tried something with the serializer below but this is yeilding some different JSON only.
class CurriculumSerializer(ModelSerializer):
grade_level = serializers.CharField(source='grade_level_dim')
subject_abbr = serializers.CharField(source='subject_abbr_dim')
product_id = serializers.IntegerField(source='dim_id')
product_title = serializers.CharField(source='title_dim')
ratings = serializers.SerializerMethodField()
class Meta:
model = Table2
fields = [
'grade_level',
'subject',
'subject_abbr',
'product_id',
'product_title',
'ratings'
]
def get_ratings(self,obj):
queryset = Table2.objects.all()
c = queryset.filter(id=obj.id, title_dim = obj.title_dim, ratings_source__isnull=False).distinct('id',)
if c.exists():
serializer = RatingsSerializer(c, many=True)
return serializer.data
else:
data = 'null'
return data
class RatingsSerializer(ModelSerializer):
review_items = serializers.SerializerMethodField()
Louisiana_rating = serializers.SerializerMethodField()
class Meta:
model = Table3
fields = ['source','report_url','review_items','Louisiana_rating']
def get_review_items(self, obj):
queryset = Table3.objects.all()
c = queryset.filter(source__iexact = 'Org1', title = obj.title_dim, grade_level = obj.grade_level, subject_abbr = obj.subject_abbr_dim)
# print(c.query)
if c.exists():
serializer = reportSerializer(c, many=True)
return serializer.data
else:
data = 'null'
return data
def get_Louisiana_rating(self, obj):
queryset = Table3.objects.all()
c = queryset.filter(source__iexact = 'Org2', title = obj.title_dim, grade_level = obj.grade_level, subject_abbr = obj.subject_abbr_dim)
if c.exists():
serializer = reportSerializer(c, many=True)
return serializer.data
else:
data = 'null'
return data
class reportSerializer(ModelSerializer):
class Meta:
model = Table3
fields = ['name',
'value',
'label',
'label_color']
class DistrictDetailSerializer(ModelSerializer):
curriculum = serializers.SerializerMethodField()
class Meta:
model = Table1
exclude = ('finance_total', 'revenue_total')
def get_curriculum(self, obj):
queryset_list = Table2.objects.all()
c = queryset_list.filter(id=obj.id)\
.distinct('col1','col2')
if c.exists():
serializer = CurriculumSerializer(c, many=True)
curriculum_map = {}
for d in serializer.data:
key = f"{d['grade_level']} {d['subject_abbr']}"
if key in curriculum_map:
curriculum_map[key].append(d)
else:
curriculum_map[key] = [d, ]
return curriculum_map
else:
data = 'null'
return data
The table3 has all details for ratings like source, report_url, name,label,value,label_colour I want this values as show in the JSON below.
This error usually occurs if the user account was not given/assigned to the Virtual Machine User Login role on the VMs.
Please check this https://learn.microsoft.com/en-us/azure/active-directory/devices/howto-vm-sign-in-azure-ad-windows#azure-role-not-assigned to assign required roles and try login.
I would like to change how an endpoint is sending a Response
Whenever I use django response like this:
return Response(serializer.data, status=status.HTTP_200_OK)
Model I use:
class StationModel(models.Model):
class Meta:
db_table = 'station'
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
shortname = models.CharField(max_length=20)
lat = models.DecimalField(max_digits=50, decimal_places=15)
lan = models.DecimalField(max_digits=50, decimal_places=15)
The response i get from an endpoint looks like this:
{
"data": [
{
"type": "Mymodel",
"id": "1",
"attributes": {
"name": "xxxxx",
"shortname": "xxxxx",
"lat": "123.000000000000000",
"lan": "213.000000000000000"
}
}
Is it possible to customize response to look like this, or at least get rid of "data" field:
{
"id": "1",
"name": "xxxxx",
"shortname": "xxxxx",
"lat": "123.000000000000000",
"lan": "213.000000000000000"
}
I got it working by setting this in settings.py
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
),
This my views.py file
class NewsChannelListView(ObjectMultipleModelAPIView):
def get_querylist(self, *args, **kwargs):
userId = self.request.user.id
queryset = [
{'queryset': News_Channel.objects.all(),
'serializer_class': NewsChannelSerializers},
{'queryset': Count.objects.filter(userId=userId),
'serializer_class': CountSerializers},
]
return queryset
I am getting following respose from my this views
{
"News_Channel": [
{
"id": 2,
"name": "Republic",
"info": "Arnab Goswami News channel",
"image": "https://fourthpillar-static.s3.amazonaws.com/media/repiblic_1bRFWNZ.png",
"website": "https://www.repu",
"total_star": 10,
"total_user": 2
},
{
"id": 1,
"name": "NDTV",
"info": "India News Media",
"image": "https://fourthpillar-static.s3.amazonaws.com/media/ndtv_WH67OhA.png",
"website": "https://ndtv.com",
"total_star": 18,
"total_user": 2
}
],
"Count": [
{
"userId": 1,
"channelId": 2,
"rate": 6
},
{
"userId": 1,
"channelId": 1,
"rate": 8
}
]
}
Is there any way I can get single object.Channel id 2 in count merge with the id 2 in news channel and Channel id 1 in count merge with the id 1 in news channel. So final Response shoule be like this
{
"News_Channel": [
{
"id": 2,
"name": "Republic",
"info": "Arnab Goswami News channel",
"image": "https://fourthpillar-static.s3.amazonaws.com/media/repiblic_1bRFWNZ.png",
"website": "https://www.repu",
"total_star": 10,
"total_user": 2,
"userId": 1,
"rate": 6
},
{
"id": 1,
"name": "NDTV",
"info": "India News Media",
"image": "https://fourthpillar-static.s3.amazonaws.com/media/ndtv_WH67OhA.png",
"website": "https://ndtv.com",
"total_star": 18,
"total_user": 2,
"userId": 1,
"rate": 8
}
],
}
Code of the model
class News_Channel(models.Model):
name = models.TextField(blank=False)
info = models.TextField(blank=False)
image = models.FileField()
website = models.TextField()
total_star = models.PositiveIntegerField(default=0)
total_user = models.IntegerField()
class Meta:
ordering = ["-id"]
def __str__(self):
return self.name
class Count(models.Model):
userId = models.ForeignKey(User, on_delete=models.CASCADE)
channelId = models.ForeignKey(News_Channel, on_delete=models.CASCADE)
rate = models.PositiveIntegerField(default=0)
class Meta:
ordering = ["-id"]
I am using django 2.1.7 and the djangorestframework==3.9.2.
I am new to Django and Django-REST and I was tasked to create a serializer.
The output of my serializer looks like this:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "a",
"description": "a",
"price": "1.00",
"images": [
{
"image_addr": "http://127.0.0.1:8000/media/products/Screenshot_from_2018-05-16_15-07-34.png",
"product": 1
},
{
"image_addr": "http://127.0.0.1:8000/media/products/Screenshot_from_2018-05-16_16-42-55.png",
"product": 1
}
]
}
]
}
How can i tweak my serializer in a way that my output would look like this:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "a",
"description": "a",
"price": "1.00",
"images": [
"http://127.0.0.1:8000/media/products/Screenshot_from_2018-05-16_15-07-34.png",
"http://127.0.0.1:8000/media/products/Screenshot_from_2018-05-16_16-42-55.png"
]
}
]
}
The serializers that I am using are:
class ProductImageSerializer(serializers.ModelSerializer):
class Meta:
model = ProductImage
fields = ('image_addr', 'product')
and
class ProductSerializer(serializers.ModelSerializer):
images = ProductImageSerializer(many=True, read_only=True)
class Meta:
model = Product
fields = ('id', 'name', 'description', 'price','images')
My models used are:
class ProductImage(models.Model):
image_addr = models.FileField(upload_to='products/',null=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='images')
and
class Product(models.Model):
name = models.CharField(max_length=150)
price = models.DecimalField(max_digits=9, decimal_places=2)
product_count = models.IntegerField(blank=True, default=0, validators=[MinValueValidator(0)])
description = models.TextField()
category = models.ManyToManyField(Category)
objects = ProductManager()
My view used is:
class CategoryProductList(generics.ListAPIView):
serializer_class = ProductSerializer
def get_queryset(self):
queryset = Product.objects.filter(category__id=self.kwargs['pk'])
return queryset
You can use SerializerMethodField for your purpose. Change your ProductSerializer as below
class ProductSerializer(serializers.ModelSerializer):
images = serializers.SerializerMethodField(read_only=True, source='images')
def get_images(self, model):
return model.images.values_list('image_addr', flat=True)
class Meta:
model = Product
fields = ('id', 'name', 'description', 'price', 'images')
I'm rendering some JSON using sinatra/contrib. I want to customise my JSON response not to include "teacher_id" in the associated record. How do I do this?
get '/teachers' do
json Teacher.includes(:courses).all.as_json(include: :courses)
end
Will render:
{
"id": 1,
"name": "Dave",
"age": 27,
"specialism": "Ruby",
"courses": [
{
"id": 1,
"title": "WDI",
"teacher_id": 1
}
]
}
I would like to remove, teacher_id:
{
"id": 1,
"name": "Dave",
"age": 27,
"specialism": "Ruby",
"courses": [
{
"id": 1,
"title": "WDI"
}
]
}
I can use the except: syntax to remove id, name, age and specialism. How can I remove the associated property?
Thanks in advance.
You can use the :except option for associations like this:
Teacher.includes(:courses).all
.as_json(include: { courses: { except: :teacher_id } })