Keyerror in django restframework

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

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 (&quot;) 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(&#39;filter&#39;))
category = data.get(&#39;category&#39;)
query_list = Event.objects.all().values(&#39;start_date&#39;).distinct()
date_list = []
for i in query_list:
for key, value in i.items():
date_list.append(datetime.datetime.strftime(value,&#39;%Y-%m-%d&#39;))
datas = []
result = {}
for dates in date_list:
result[dates]= []
query = Event.objects.filter(start_date=dates).order_by(&#39;start_date&#39;)
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=(&#39;id&#39;,&#39;name&#39;,&#39;category&#39;,&#39;start_date&#39;,&#39;end_date&#39;,&#39;status&#39;)
def get_category(self, obj):
category = {}
if obj.category:
category[&#39;id&#39;] = obj.category.id
category[&#39;name&#39;] = obj.category.name
return category
else:
category = &quot;&quot;
return category
def get_status(self,obj):
current_date =  datetime.strftime(datetime.today(),&#39;%Y-%m-%d&#39;)
start_date = datetime.strftime(obj.start_date,&#39;%Y-%m-%d&#39;)
if obj.end_date is not None:
end_date = datetime.strftime(obj.end_date,&#39;%Y-%m-%d&#39;)
if start_date == end_date and start_date &lt; current_date:
return &quot;completed&quot;
elif start_date &lt; current_date and end_date &lt; current_date:
return &quot;completed&quot;
elif start_date &lt; current_date and end_date &gt; current_date:
return &quot;progress&quot;
elif start_date == current_date:
return &quot;progress&quot;
else:
return &quot;upcoming&quot;
else:
if start_date &lt; current_date:
return &quot;completed&quot;
elif start_date == current_date:
return &quot;progress&quot;
else:
return &quot;upcomng&quot;

Keyerror in django restframework

Expecting output:

[
{
&quot;2023-06-01&quot;: [
{
&quot;name&quot;: &quot;event 1&quot;,
&quot;start_date&quot;: &quot;2023-06-01&quot;,
&quot;end_date&quot;: &quot;2023-06-07&quot;
}
]
},
{
&quot;2023-06-01&quot;: [
{
&quot;name&quot;: &quot;event 2&quot;,
&quot;start_date&quot;: &quot;2023-06-01&quot;,
&quot;end_date&quot;: &quot;2023-06-07&quot;
},
{
&quot;name&quot;: &quot;event 3&quot;,
&quot;start_date&quot;: &quot;2023-06-01&quot;,
&quot;end_date&quot;: &quot;2023-06-07&quot;
}
]
}
...
]

答案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(&quot;filter&quot;) or None
        if filter_param:
            filter_param_data = json.loads(filter_param)
            category = filter_param_data.get(&quot;category&quot;)

        data = []
        date_list = (
            Event.objects.all()
            .values_list(&quot;start_date&quot;, flat=True)
            .distinct()
        )

        for date in date_list:
            event_list = Event.objects.filter(start_date=date)
            data.append({&quot;day&quot;: date, &quot;events&quot;: 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).

[
  {
      &quot;day&quot;: &quot;2023-06-01&quot;,
      &quot;events&quot;: [
          {
              &quot;id&quot;: 1,
              &quot;name&quot;: &quot;Event 1&quot;,
              &quot;category&quot;: {
                  &quot;id&quot;: 1,
                  &quot;name&quot;: &quot;some category&quot;
              },
              &quot;start_date&quot;: &quot;2023-06-01&quot;,
              &quot;end_date&quot;: &quot;2023-06-07&quot;,
              &quot;status&quot;: &quot;completed&quot;
          },
          {
              &quot;id&quot;: 2,
              &quot;name&quot;: &quot;Event 2&quot;,
              &quot;category&quot;: {
                  &quot;id&quot;: 1,
                  &quot;name&quot;: &quot;some category&quot;
              },
              &quot;start_date&quot;: &quot;2023-06-01&quot;,
              &quot;end_date&quot;: &quot;2023-06-07&quot;,
              &quot;status&quot;: &quot;completed&quot;
          },
          {
              &quot;id&quot;: 3,
              &quot;name&quot;: &quot;Event 3&quot;,
              &quot;category&quot;: {
                  &quot;id&quot;: 1,
                  &quot;name&quot;: &quot;some category&quot;
              },
              &quot;start_date&quot;: &quot;2023-06-01&quot;,
              &quot;end_date&quot;: &quot;2023-06-07&quot;,
              &quot;status&quot;: &quot;completed&quot;
          }
      ]
  }
]

<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 *&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:
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)

&lt;h2&gt;Alternatively&lt;/h2&gt;
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(&quot;filter&quot;) or None
if filter_param:
filter_param_data = json.loads(filter_param)
category = filter_param_data.get(&quot;category&quot;)
data = []
date_list = (
Event.objects.all()
.values_list(&quot;start_date&quot;, flat=True)
.distinct()
)
for date in date_list:
event_list = Event.objects.filter(start_date=date)
data.append({&quot;day&quot;: date, &quot;events&quot;: 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>

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:

确定