英文:
Keyerror in django restframework
问题
Here's the translation of the provided code:
**Views.py**
class EventCalenderEventListView(ListAPIView):
permission_classes = [AllowAny,]
serializer_class = serializer.EventCalenderSerializer
def get_queryset(self, *args, **kwargs):
data = json.loads(self.request.GET.get('filter'))
category = data.get('category')
query_list = Event.objects.all().values('start_date').distinct()
date_list = []
for i in query_list:
for key, value in i.items():
date_list.append(datetime.datetime.strftime(value, '%Y-%m-%d'))
datas = []
result = {}
for dates in date_list:
result[dates] = []
query = Event.objects.filter(start_date=dates).order_by('start_date')
for i in query:
result[dates].append(i)
datas.append(result)
result = {}
return datas
**Models.py**
class Event(BaseFields):
name = models.CharField(max_length=250)
category = models.ForeignKey(EventCategory, on_delete=models.CASCADE, null=True, blank=True)
other_event_category = models.CharField(max_length=250, null=True, blank=True)
meeting_link = models.CharField(max_length=250, null=True, blank=True)
description = models.TextField(null=True, blank=True)
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
**serializer.py**
class EventCalenderSerializer(ModelSerializer):
category = SerializerMethodField()
status = SerializerMethodField()
class Meta:
model = Event
fields = fields = ('id', 'name', 'category', 'start_date', 'end_date', 'status')
def get_category(self, obj):
category = {}
if obj.category:
category['id'] = obj.category.id
category['name'] = obj.category.name
return category
else:
category = ""
return category
def get_status(self, obj):
current_date = datetime.strftime(datetime.today(), '%Y-%m-%d')
start_date = datetime.strftime(obj.start_date, '%Y-%m-%d')
if obj.end_date is not None:
end_date = datetime.strftime(obj.end_date, '%Y-%m-%d')
if start_date == end_date and start_date < current_date:
return "completed"
elif start_date < current_date and end_date < current_date:
return "completed"
elif start_date < current_date and end_date > current_date:
return "progress"
elif start_date == current_date:
return "progress"
else:
return "upcoming"
else:
if start_date < current_date:
return "completed"
elif start_date == current_date:
return "progress"
else:
return "upcoming"
Note: I've replaced the HTML entity codes ("
) with actual double quotes for clarity.
英文:
Views.py
class EventCalenderEventListView(ListAPIView):
permission_classes=[AllowAny,]
serializer_class = serializer.EventCalenderSerializer
def get_queryset(self, *args, **kwargs):
data = json.loads(self.request.GET.get('filter'))
category = data.get('category')
query_list = Event.objects.all().values('start_date').distinct()
date_list = []
for i in query_list:
for key, value in i.items():
date_list.append(datetime.datetime.strftime(value,'%Y-%m-%d'))
datas = []
result = {}
for dates in date_list:
result[dates]= []
query = Event.objects.filter(start_date=dates).order_by('start_date')
for i in query:
result[dates].append(i)
datas.append(result)
result = {}
return datas
Models.py
class Event(BaseFields):
name = models.CharField(max_length=250)
category = models.ForeignKey(EventCategory,on_delete=models.CASCADE,null=True,blank=True)
other_event_category = models.CharField(max_length=250,null=True,blank=True)
meeting_link = models.CharField(max_length=250,null=True,blank=True)
description = models.TextField(null=True,blank=True)
start_date = models.DateField(null=True,blank=True)
end_date = models.DateField(null=True,blank=True)
serializer.py
class EventCalenderSerializer(ModelSerializer):
category = SerializerMethodField()
status = SerializerMethodField()
class Meta:
model = Event
fields = fields=('id','name','category','start_date','end_date','status')
def get_category(self, obj):
category = {}
if obj.category:
category['id'] = obj.category.id
category['name'] = obj.category.name
return category
else:
category = ""
return category
def get_status(self,obj):
current_date = datetime.strftime(datetime.today(),'%Y-%m-%d')
start_date = datetime.strftime(obj.start_date,'%Y-%m-%d')
if obj.end_date is not None:
end_date = datetime.strftime(obj.end_date,'%Y-%m-%d')
if start_date == end_date and start_date < current_date:
return "completed"
elif start_date < current_date and end_date < current_date:
return "completed"
elif start_date < current_date and end_date > current_date:
return "progress"
elif start_date == current_date:
return "progress"
else:
return "upcoming"
else:
if start_date < current_date:
return "completed"
elif start_date == current_date:
return "progress"
else:
return "upcomng"
Expecting output:
[
{
"2023-06-01": [
{
"name": "event 1",
"start_date": "2023-06-01",
"end_date": "2023-06-07"
}
]
},
{
"2023-06-01": [
{
"name": "event 2",
"start_date": "2023-06-01",
"end_date": "2023-06-07"
},
{
"name": "event 3",
"start_date": "2023-06-01",
"end_date": "2023-06-07"
}
]
}
...
]
答案1
得分: 0
以下是您要翻译的部分:
"The response of .get_queryset
is what is passed to .list
method that will serialize and return data ready for display. Currently, you are deforming this into something that does not correspond to your serializer
:
[
{'2023-06-01':
[
<Event: Event object (1)>,
<Event: Event object (2)>,
<Event: Event object (3)>
]
}
]
Also, that is different from the structure you posted (as expected output) in your question, I will assume that what you built with code is the correct one.
So, basically what you need to do is serialize the list of events inside your key values. We can work around that by overriding the .list
method. And, loop through your "QuerySet" (that is actually an Array
of dictionaries that contains one key with a list of Event
objects), in this way serializing this list and recreating your response:
views.py
class EventCalenderEventListView(ListAPIView):
...
def get_queryset(self, *args, **kwargs):
...
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
data = []
for event_date in queryset:
for key, value in event_date.items():
serializer = self.get_serializer(value, many=True)
data.append({key: serializer.data})
return Response(data)
<h2>Alternatively</h2>
I propose that you clean your view, by making use of methods provided by the QuerySet API and that you structure your data in a different manner, so we can directly serialize the data with a Wrapper
:
serializers.py
class EventCalenderSerializer(ModelSerializer):
...
class Wrapper(serializers.Serializer):
day = serializers.DateField()
events = EventCalenderSerializer(many=True)
views.py
class EventCalenderEventListView(ListAPIView):
permission_classes = [
AllowAny,
]
serializer_class = Wrapper
def get_queryset(self, *args, **kwargs):
# We can go arround the param
filter_param = self.request.GET.get("filter") or None
if filter_param:
filter_param_data = json.loads(filter_param)
category = filter_param_data.get("category")
data = []
date_list = (
Event.objects.all()
.values_list("start_date", flat=True)
.distinct()
)
for date in date_list:
event_list = Event.objects.filter(start_date=date)
data.append({"day": date, "events": event_list})
return data
Lastly, a response sample, based on EventCalenderSerializer
. If you want the same fields as expected in your question, then remove the respective ones from your original serializer (same is valid for the previous solution).
[
{
"day": "2023-06-01",
"events": [
{
"id": 1,
"name": "Event 1",
"category": {
"id": 1,
"name": "some category"
},
"start_date": "2023-06-01",
"end_date": "2023-06-07",
"status": "completed"
},
{
"id": 2,
"name": "Event 2",
"category": {
"id": 1,
"name": "some category"
},
"start_date": "2023-06-01",
"end_date": "2023-06-07",
"status": "completed"
},
{
"id": 3,
"name": "Event 3",
"category": {
"id": 1,
"name": "some category"
},
"start_date": "2023-06-01",
"end_date": "2023-06-07",
"status": "completed"
}
]
}
]
<details>
<summary>英文:</summary>
The response of `.get_queryset` is what is passed to `.list` method that will serialize and return data ready for display. Currently, you are deforming this into something that does not correspond to your `serializer`:
[
{'2023-06-01':
[
<Event: Event object (1)>,
<Event: Event object (2)>,
<Event: Event object (3)>
]
}
]
Also, that is different from the structure you posted (as expected output) in your question, I will assume that what you built with code is the correct one.
So, basically what you need to do is serialize the list of events inside your key values. We can work around that by overriding the `.list` method. And, loop through your *"QuerySet"* (that is actually an `Array` of dictionaries that contains one key with a list of `Event` objects), in this way serializing this list and recreating your response:
views.py
class EventCalenderEventListView(ListAPIView):
...
def get_queryset(self, *args, **kwargs):
...
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
data = []
for event_date in queryset:
for key, value in event_date.items():
serializer = self.get_serializer(value, many=True)
data.append({key: serializer.data})
return Response(data)
<h2>Alternatively</h2>
I propose that you clean your view, by making use of methods provided by the [QuerySet API][1] and that you structure your data in a different manner, so we can directly serialize the data with a `Wrapper`:
serializers.py
class EventCalenderSerializer(ModelSerializer):
...
class Wrapper(serializers.Serializer):
day = serializers.DateField()
events = EventCalenderSerializer(many=True)
views.py
class EventCalenderEventListView(ListAPIView):
permission_classes = [
AllowAny,
]
serializer_class = Wrapper
def get_queryset(self, *args, **kwargs):
# We can go arround the param
filter_param = self.request.GET.get("filter") or None
if filter_param:
filter_param_data = json.loads(filter_param)
category = filter_param_data.get("category")
data = []
date_list = (
Event.objects.all()
.values_list("start_date", flat=True)
.distinct()
)
for date in date_list:
event_list = Event.objects.filter(start_date=date)
data.append({"day": date, "events": event_list})
return data
Lastly, a response sample, based on `EventCalenderSerializer`. If you want the same fields as expected in your question, then remove the respective ones from your original serializer (same is valid for the previous solution).
[
{
"day": "2023-06-01",
"events": [
{
"id": 1,
"name": "Event 1",
"category": {
"id": 1,
"name": "some category"
},
"start_date": "2023-06-01",
"end_date": "2023-06-07",
"status": "completed"
},
{
"id": 2,
"name": "Event 2",
"category": {
"id": 1,
"name": "some category"
},
"start_date": "2023-06-01",
"end_date": "2023-06-07",
"status": "completed"
},
{
"id": 3,
"name": "Event 3",
"category": {
"id": 1,
"name": "some category"
},
"start_date": "2023-06-01",
"end_date": "2023-06-07",
"status": "completed"
}
]
}
]
[1]: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#values-list
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论