how to filter the data from django database for a week?

45 Views Asked by At

I'm filtering the data from django database using datetime__range filter providing the dates start_of_week and end_of_week and I have another list in python that contains the dates of that week so when I got the data from the range filter I count it for each day using the date from the week but for some users the result I got contain the data of one day earlier so it shows error because the result contain I date earlier of start_of_week date which was not in week_dates list so it shows key error. How Should I filter the data so that I got proper data between the range. I'm adding the models.py and admin.py and the screenshot of terminal.

the model of User_details in models.py

SUGESSTION_CHOICES = (

    (0,'Pending Verification'),
    (1, 'User Accepts Prediction'),
    (2,'User Suggestion Incorrect'),
    (3,'Actual Prediction Incorrect'),
    (4,'Unsupported Breed'),
    (5,'In Progress'),
    (6,'Model Successfully Trained'),

)    

PREDICTION_CHOICES = (
    (0,'By Image'),
    (1, 'By Video')
)    

PREDICTION_STATUS = (
    (0,'Predicted Sucessfully'),
    (1, 'Not Able To Predict'),
    (2, 'Junk'),
)

   
class History(models.Model):
    user= models.ForeignKey(User_details, related_name='history', on_delete=models.CASCADE)
    image=models.ImageField(upload_to=get_upload_path,null=True)
    predictions= models.TextField(default=dict(),null=True,verbose_name="Predictions")
    predictions_type=models.IntegerField(choices=PREDICTION_CHOICES, default=0,verbose_name="Prediction Type")
    predictions_status=models.IntegerField(choices=PREDICTION_STATUS, default=0,verbose_name="Prediction Status")
    predicted_breed_id = models.PositiveIntegerField(null=True,blank=True,verbose_name="Predicted Breed Id")
    moods= models.TextField(default=dict(),null=True,verbose_name="Moods")
    user_platform= models.CharField(max_length=50,default='',null=True,verbose_name="User Platform")
    user_device= models.CharField(max_length=50,default='',null=True,verbose_name="User Device ID")
    app_version= models.CharField(max_length=50,default='',null=True,verbose_name="App Version")
    request_headers= models.TextField(default='',null=True,verbose_name="Request Headers")
    user_suggestion= models.CharField(max_length=50,default='',null=True,verbose_name="User Suggestion")
    suggestion_status = models.IntegerField(choices=SUGESSTION_CHOICES, default=0)
    user_suggestion_id= models.PositiveIntegerField(null=True,blank=True,verbose_name="Suggestion Breed Id")
    api_version= models.CharField(max_length=25,default='',null=True,verbose_name="Version")
    is_junk=models.BooleanField(default=False,null=True)
    is_deleted=models.BooleanField(default=False,null=True)
    app_type=models.SmallIntegerField(default=0)
    datetime = models.DateTimeField(auto_now_add=True, verbose_name="Predicted On")
    #datetime = models.DateTimeField(auto_now=False, auto_now_add=True, verbose_name="Predicted On")

    def history_image_preview(self):
        if self.image:
            return mark_safe('<img src="{0}" width="150" height="150" />'.format(self.image.url))

    class Meta:
        verbose_name = ("User Prediction History")
        verbose_name_plural = ("User Prediction History")

admin.py

    @admin.register(User_details)
class UserDetailsAdmin(admin.ModelAdmin):
    
#    inlines = [PostInline, FavoritesInline, HistoryInline]
    list_display = ['id', 'token', 'user_name', 'History_count', 'Prediction_Limit','used_limit','user_email', 'google_id', 'facebook_id',
                    'apple_id', 'profile_preview', 'user_phone_no', 'app_type', 'is_guest', 'is_deleted', 'datetime']

    readonly_fields = ['datetime']
    search_fields = ['token', 'user_name', 'user_email']

    list_filter = (AppTypeFilter, UserTypeFilter,
                   GuestTypeFilter, ('datetime', DateRangeFilter),('history__datetime', DateRangeFilter),('Prediction_usage_log__date',DateRangeFilter))
    
    def get_queryset(self, request):
        qs = super(UserDetailsAdmin, self).get_queryset(request)
        
        start_date = request.GET.get('Prediction_usage_log__date__range__gte')
        end_date_string = request.GET.get('Prediction_usage_log__date__range__lte')
        try:
            end_date_object = datetime.datetime.strptime(end_date_string, "%m-%d-%Y")
            # Add one day using timedelta
            end_date = str(end_date_object + timedelta(days=1))
        except:
            end_date = end_date_string

        if start_date and end_date:
            qs = qs.filter(Prediction_usage_log__date__range=[start_date, end_date])
            limit = qs.annotate(history_count=Count('history'), prediction_limit_sum=Sum('Prediction_usage_log__daily_prediction_limit'),used_limit_sum=Sum('Prediction_usage_log__used_limit'))

        else:
            limit = qs.annotate(history_count=Count('history'), prediction_limit_sum=Sum('Prediction_usage_log__daily_prediction_limit'),used_limit_sum=Sum('Prediction_usage_log__used_limit'))

        return limit
    

    def History_count(self, obj):
        return obj.history_count
    History_count.admin_order_field = "history_count"
    History_count.short_description = "History Count"

    def Prediction_Limit(self, obj):
        return obj.prediction_limit_sum
    Prediction_Limit.admin_order_field = 'Prediction_Limit'
    Prediction_Limit.short_description = 'Prediction Limit'

    def used_limit(self,obj):
        return obj.used_limit_sum
    used_limit.admin_order_field = 'used_limit'
    used_limit.short_description = 'Used Limit'

    def change_view(self, request, object_id, form_url='', extra_context=None):

        # now = datetime.datetime.now()
        # start_of_day = datetime.datetime.combine(now.date(), datetime.time.min)

        extra_context = extra_context or {} 
        # Retrieve the specific User_details object
        user_details = self.get_object(request, object_id)

        print("request.GET.get(start_date)")
        print(request.GET.get("start_date"))

        if user_details:
            if request.GET.get("next_week") or request.GET.get("previous_week"):
                try:
                    date = datetime.datetime.strptime(request.GET.get("start_date"), '%B %d, %Y').date()
                    #timezone_aware_datetime = timezone.make_aware(date, timezone.get_current_timezone())
                    timezone_aware_datetime = date
                    #timezone_aware_datetime = utc.localize(date)
                except:
                    corrected_date_string = request.GET.get("start_date").replace("Sept.", "Sep.")
                    date = datetime.datetime.strptime(corrected_date_string, "%b. %d, %Y").date()
                    #timezone_aware_datetime = timezone.make_aware(date, timezone.get_current_timezone())
                    timezone_aware_datetime = date
                    #timezone_aware_datetime = utc.localize(date)

                if request.GET.get("next_week"):
                    start_of_week = timezone_aware_datetime + timedelta(days=7)
                    end_of_week = start_of_week + timedelta(days=6)

                elif request.GET.get("previous_week"):
                    end_of_week = timezone_aware_datetime - timedelta(days=1)
                    start_of_week = timezone_aware_datetime - timedelta(days=7)
            else:
                current_date = timezone.now().date()
                start_of_week = current_date - timedelta(days=current_date.weekday())
                end_of_week = start_of_week + timedelta(days=6)
            


            print("start of the week.........end_of_week")
            print(start_of_week,"..........",end_of_week)
            print()
            print()

            week_dates = [start_of_week + timedelta(days=i) for i in range(7)]
            print("week_dates.........")
            print(week_dates)
            print()
            print()
            #------------------------- test -------------------------
            
            # start_date_test = datetime.datetime.strptime("June 19, 2023", "%B %d, %Y")
            # start_of_day = datetime.datetime.combine(start_date_test.date(), datetime.time.min)
            # end_date = datetime.datetime.strptime("June 25, 2023", "%B %d, %Y")
            # end_of_day = datetime.datetime.combine(end_date.date(), datetime.time(23, 59, 59))
            
            result = History.objects.filter(user__user_name=user_details, datetime__range=(start_of_week, end_of_week)).values('datetime').annotate(count=Count('*'))
            prediction_counts_by_day = {date: 0 for date in week_dates}


            print("result.....")
            print(result)
            print()


            for entry in result:
                    datetime1 = entry['datetime'].date()
                    count = entry['count']
                    prediction_counts_by_day[datetime1] += count

            extra_context['history_counts'] = prediction_counts_by_day
            extra_context['start_date'] = start_of_week
            extra_context['week_dates'] = week_dates
            extra_context['total_predictions'] = result.count()
    
        return super().change_view(request, object_id, form_url=form_url, extra_context=extra_context)

when the start_of_week is 2023-06-19 and the end_of_week is 2023-06-25 then also I got the data like this

<QuerySet [{'datetime': datetime.datetime(2023, 6, 18, 18, 31, 25, 398616, tzinfo=datetime.timezone.utc), 'count': 1}, {'datetime': datetime.datetime(2023, 6, 18, 18, 31, 47, 364849, tzinfo=datetime.timezone.utc), 'count': 1}, {'datetime': datetime.datetime(2023, 6, 18, 18, 31, 59, 994095, tzinfo=datetime.timezone.utc), 'count': 1}, {'datetime': datetime.datetime(2023, 6, 18, 18, 32, 29, 877885, tzinfo=datetime.timezone.utc), 'count': 1}, {'datetime': datetime.datetime(2023, 6, 18, 18, 33, 0, 188511, tzinfo=datetime.timezone.utc), 'count': 1}]>

screenshot of the terminal

0

There are 0 best solutions below