Keyerror in django restframework

huangapple go评论94阅读模式
英文:

Keyerror in django restframework

问题

Here's the translation of the provided code:

  1. **Views.py**
  2. class EventCalenderEventListView(ListAPIView):
  3. permission_classes = [AllowAny,]
  4. serializer_class = serializer.EventCalenderSerializer
  5. def get_queryset(self, *args, **kwargs):
  6. data = json.loads(self.request.GET.get('filter'))
  7. category = data.get('category')
  8. query_list = Event.objects.all().values('start_date').distinct()
  9. date_list = []
  10. for i in query_list:
  11. for key, value in i.items():
  12. date_list.append(datetime.datetime.strftime(value, '%Y-%m-%d'))
  13. datas = []
  14. result = {}
  15. for dates in date_list:
  16. result[dates] = []
  17. query = Event.objects.filter(start_date=dates).order_by('start_date')
  18. for i in query:
  19. result[dates].append(i)
  20. datas.append(result)
  21. result = {}
  22. return datas
  23. **Models.py**
  24. class Event(BaseFields):
  25. name = models.CharField(max_length=250)
  26. category = models.ForeignKey(EventCategory, on_delete=models.CASCADE, null=True, blank=True)
  27. other_event_category = models.CharField(max_length=250, null=True, blank=True)
  28. meeting_link = models.CharField(max_length=250, null=True, blank=True)
  29. description = models.TextField(null=True, blank=True)
  30. start_date = models.DateField(null=True, blank=True)
  31. end_date = models.DateField(null=True, blank=True)
  32. **serializer.py**
  33. class EventCalenderSerializer(ModelSerializer):
  34. category = SerializerMethodField()
  35. status = SerializerMethodField()
  36. class Meta:
  37. model = Event
  38. fields = fields = ('id', 'name', 'category', 'start_date', 'end_date', 'status')
  39. def get_category(self, obj):
  40. category = {}
  41. if obj.category:
  42. category['id'] = obj.category.id
  43. category['name'] = obj.category.name
  44. return category
  45. else:
  46. category = ""
  47. return category
  48. def get_status(self, obj):
  49. current_date = datetime.strftime(datetime.today(), '%Y-%m-%d')
  50. start_date = datetime.strftime(obj.start_date, '%Y-%m-%d')
  51. if obj.end_date is not None:
  52. end_date = datetime.strftime(obj.end_date, '%Y-%m-%d')
  53. if start_date == end_date and start_date < current_date:
  54. return "completed"
  55. elif start_date < current_date and end_date < current_date:
  56. return "completed"
  57. elif start_date < current_date and end_date > current_date:
  58. return "progress"
  59. elif start_date == current_date:
  60. return "progress"
  61. else:
  62. return "upcoming"
  63. else:
  64. if start_date < current_date:
  65. return "completed"
  66. elif start_date == current_date:
  67. return "progress"
  68. else:
  69. return "upcoming"

Note: I've replaced the HTML entity codes (&quot;) with actual double quotes for clarity.

英文:

Views.py

  1. class EventCalenderEventListView(ListAPIView):
  2. permission_classes=[AllowAny,]
  3. serializer_class = serializer.EventCalenderSerializer
  4. def get_queryset(self, *args, **kwargs):
  5. data = json.loads(self.request.GET.get(&#39;filter&#39;))
  6. category = data.get(&#39;category&#39;)
  7. query_list = Event.objects.all().values(&#39;start_date&#39;).distinct()
  8. date_list = []
  9. for i in query_list:
  10. for key, value in i.items():
  11. date_list.append(datetime.datetime.strftime(value,&#39;%Y-%m-%d&#39;))
  12. datas = []
  13. result = {}
  14. for dates in date_list:
  15. result[dates]= []
  16. query = Event.objects.filter(start_date=dates).order_by(&#39;start_date&#39;)
  17. for i in query:
  18. result[dates].append(i)
  19. datas.append(result)
  20. result = {}
  21. return datas

Models.py

  1. class Event(BaseFields):
  2. name = models.CharField(max_length=250)
  3. category = models.ForeignKey(EventCategory,on_delete=models.CASCADE,null=True,blank=True)
  4. other_event_category = models.CharField(max_length=250,null=True,blank=True)
  5. meeting_link = models.CharField(max_length=250,null=True,blank=True)
  6. description = models.TextField(null=True,blank=True)
  7. start_date = models.DateField(null=True,blank=True)
  8. end_date = models.DateField(null=True,blank=True)

serializer.py

  1. class EventCalenderSerializer(ModelSerializer):
  2. category = SerializerMethodField()
  3. status = SerializerMethodField()
  4. class Meta:
  5. model = Event
  6. fields = fields=(&#39;id&#39;,&#39;name&#39;,&#39;category&#39;,&#39;start_date&#39;,&#39;end_date&#39;,&#39;status&#39;)
  7. def get_category(self, obj):
  8. category = {}
  9. if obj.category:
  10. category[&#39;id&#39;] = obj.category.id
  11. category[&#39;name&#39;] = obj.category.name
  12. return category
  13. else:
  14. category = &quot;&quot;
  15. return category
  16. def get_status(self,obj):
  17. current_date = datetime.strftime(datetime.today(),&#39;%Y-%m-%d&#39;)
  18. start_date = datetime.strftime(obj.start_date,&#39;%Y-%m-%d&#39;)
  19. if obj.end_date is not None:
  20. end_date = datetime.strftime(obj.end_date,&#39;%Y-%m-%d&#39;)
  21. if start_date == end_date and start_date &lt; current_date:
  22. return &quot;completed&quot;
  23. elif start_date &lt; current_date and end_date &lt; current_date:
  24. return &quot;completed&quot;
  25. elif start_date &lt; current_date and end_date &gt; current_date:
  26. return &quot;progress&quot;
  27. elif start_date == current_date:
  28. return &quot;progress&quot;
  29. else:
  30. return &quot;upcoming&quot;
  31. else:
  32. if start_date &lt; current_date:
  33. return &quot;completed&quot;
  34. elif start_date == current_date:
  35. return &quot;progress&quot;
  36. else:
  37. return &quot;upcomng&quot;

Keyerror in django restframework

Expecting output:

  1. [
  2. {
  3. &quot;2023-06-01&quot;: [
  4. {
  5. &quot;name&quot;: &quot;event 1&quot;,
  6. &quot;start_date&quot;: &quot;2023-06-01&quot;,
  7. &quot;end_date&quot;: &quot;2023-06-07&quot;
  8. }
  9. ]
  10. },
  11. {
  12. &quot;2023-06-01&quot;: [
  13. {
  14. &quot;name&quot;: &quot;event 2&quot;,
  15. &quot;start_date&quot;: &quot;2023-06-01&quot;,
  16. &quot;end_date&quot;: &quot;2023-06-07&quot;
  17. },
  18. {
  19. &quot;name&quot;: &quot;event 3&quot;,
  20. &quot;start_date&quot;: &quot;2023-06-01&quot;,
  21. &quot;end_date&quot;: &quot;2023-06-07&quot;
  22. }
  23. ]
  24. }
  25. ...
  26. ]

答案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:

  1. [
  2. {'2023-06-01':
  3. [
  4. <Event: Event object (1)>,
  5. <Event: Event object (2)>,
  6. <Event: Event object (3)>
  7. ]
  8. }
  9. ]

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

  1. class EventCalenderEventListView(ListAPIView):
  2. ...
  3. def get_queryset(self, *args, **kwargs):
  4. ...
  5. def list(self, request, *args, **kwargs):
  6. queryset = self.get_queryset()
  7. data = []
  8. for event_date in queryset:
  9. for key, value in event_date.items():
  10. serializer = self.get_serializer(value, many=True)
  11. data.append({key: serializer.data})
  12. 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

  1. class EventCalenderSerializer(ModelSerializer):
  2. ...
  3. class Wrapper(serializers.Serializer):
  4. day = serializers.DateField()
  5. events = EventCalenderSerializer(many=True)

views.py

  1. class EventCalenderEventListView(ListAPIView):
  2. permission_classes = [
  3. AllowAny,
  4. ]
  5. serializer_class = Wrapper
  6. def get_queryset(self, *args, **kwargs):
  7. # We can go arround the param
  8. filter_param = self.request.GET.get(&quot;filter&quot;) or None
  9. if filter_param:
  10. filter_param_data = json.loads(filter_param)
  11. category = filter_param_data.get(&quot;category&quot;)
  12. data = []
  13. date_list = (
  14. Event.objects.all()
  15. .values_list(&quot;start_date&quot;, flat=True)
  16. .distinct()
  17. )
  18. for date in date_list:
  19. event_list = Event.objects.filter(start_date=date)
  20. data.append({&quot;day&quot;: date, &quot;events&quot;: event_list})
  21. 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).

  1. [
  2. {
  3. &quot;day&quot;: &quot;2023-06-01&quot;,
  4. &quot;events&quot;: [
  5. {
  6. &quot;id&quot;: 1,
  7. &quot;name&quot;: &quot;Event 1&quot;,
  8. &quot;category&quot;: {
  9. &quot;id&quot;: 1,
  10. &quot;name&quot;: &quot;some category&quot;
  11. },
  12. &quot;start_date&quot;: &quot;2023-06-01&quot;,
  13. &quot;end_date&quot;: &quot;2023-06-07&quot;,
  14. &quot;status&quot;: &quot;completed&quot;
  15. },
  16. {
  17. &quot;id&quot;: 2,
  18. &quot;name&quot;: &quot;Event 2&quot;,
  19. &quot;category&quot;: {
  20. &quot;id&quot;: 1,
  21. &quot;name&quot;: &quot;some category&quot;
  22. },
  23. &quot;start_date&quot;: &quot;2023-06-01&quot;,
  24. &quot;end_date&quot;: &quot;2023-06-07&quot;,
  25. &quot;status&quot;: &quot;completed&quot;
  26. },
  27. {
  28. &quot;id&quot;: 3,
  29. &quot;name&quot;: &quot;Event 3&quot;,
  30. &quot;category&quot;: {
  31. &quot;id&quot;: 1,
  32. &quot;name&quot;: &quot;some category&quot;
  33. },
  34. &quot;start_date&quot;: &quot;2023-06-01&quot;,
  35. &quot;end_date&quot;: &quot;2023-06-07&quot;,
  36. &quot;status&quot;: &quot;completed&quot;
  37. }
  38. ]
  39. }
  40. ]
  1. <details>
  2. <summary>英文:</summary>
  3. 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)>
]
}
]

  1. 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.
  2. 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 *&quot;QuerySet&quot;* (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:
  3. views.py

class EventCalenderEventListView(ListAPIView):
...

  1. def get_queryset(self, *args, **kwargs):
  2. ...
  3. def list(self, request, *args, **kwargs):
  4. queryset = self.get_queryset()
  5. data = []
  6. for event_date in queryset:
  7. for key, value in event_date.items():
  8. serializer = self.get_serializer(value, many=True)
  9. data.append({key: serializer.data})
  10. return Response(data)
  1. &lt;h2&gt;Alternatively&lt;/h2&gt;
  2. 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`:
  3. serializers.py

class EventCalenderSerializer(ModelSerializer):
...

class Wrapper(serializers.Serializer):
day = serializers.DateField()
events = EventCalenderSerializer(many=True)

  1. views.py

class EventCalenderEventListView(ListAPIView):
permission_classes = [
AllowAny,
]
serializer_class = Wrapper

  1. def get_queryset(self, *args, **kwargs):
  2. # We can go arround the param
  3. filter_param = self.request.GET.get(&quot;filter&quot;) or None
  4. if filter_param:
  5. filter_param_data = json.loads(filter_param)
  6. category = filter_param_data.get(&quot;category&quot;)
  7. data = []
  8. date_list = (
  9. Event.objects.all()
  10. .values_list(&quot;start_date&quot;, flat=True)
  11. .distinct()
  12. )
  13. for date in date_list:
  14. event_list = Event.objects.filter(start_date=date)
  15. data.append({&quot;day&quot;: date, &quot;events&quot;: event_list})
  16. return data
  1. 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. [1]: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#values-list
  2. </details>

huangapple
  • 本文由 发表于 2023年6月13日 03:26:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76459745.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定