Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to use count() to get items between specific dates

With this code I am able to get all orders items that is related to Article but here is the problem, I want to get the number of orders that are between two dates that are between the assigned timestamp.How can I do it?


class Order(models.Model):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    author = models.ForeignKey(User,  on_delete=models.CASCADE,related_name='ordersauthor')
    article = models.ForeignKey(Article, null=True, blank=True, on_delete=models.CASCADE,related_name='ordersarticle')
    timestamp = models.DateTimeField(auto_now_add=True)
    total_price = models.FloatField(default='0', validators=[MaxValueValidator(99999999999999999999)])

class ArticleSerializer(serializers.ModelSerializer):
    orders = serializers.SerializerMethodField(read_only=True)


    class Meta:
        model = Article
        fields = '__all__'

    def get_orders(self, language):
        return language.ordersarticle.count()

Initial Output:

{
            .....,
             "orders": 4, // All orders
        },

Expected Output:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

{
            .....,
             "orders": 1, // Orders between 4th and 11th of march (Example)
        },

Update:

class ArticleViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated,)
    queryset = Article.objects.all().order_by('-timestamp')
    serializer_class = ArticleSerializer
    filter_backends = [filters.SearchFilter,DjangoFilterBackend]
    pagination_class = StandardResultsSetPagination
    search_fields = ['^articlechoices__item','^caption','^name']
    filterset_fields = ['author','price','location','category']

>Solution :

You can filter with:

from datetime import date


class ArticleSerializer(serializers.ModelSerializer):
    orders = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Article
        fields = '__all__'

    def get_orders(self, language):
        return language.ordersarticle.filter(
            timestamp__range=(date(2024, 3, 4), date(2024, 3, 7))
        ).count()

but this is not a good idea: if you have to serialize for example multiple such Articles, it will make a query per item.

We can calculate these in advance with:

from django.db.models import Count, Q


class ArticleViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated,)
    queryset = Article.objects.all().order_by('-timestamp')
    serializer_class = ArticleSerializer
    filter_backends = [filters.SearchFilter, DjangoFilterBackend]
    pagination_class = StandardResultsSetPagination
    search_fields = ['^articlechoices__item', '^caption', '^name']
    filterset_fields = ['author', 'price', 'location', 'category']

    def get_queryset(self, *args, **kwargs):
        return (
            super()
            .get_queryset(*args, **kwargs)
            .annotate(
                num_orders=Count(
                    'ordersarticle',
                    filter=Q(
                        ordersarticle__timestamp__range=(date(2024, 3, 4), date(2024, 3, 7))
                    ),
                )
            )
        )

and serialize with:

class ArticleSerializer(serializers.ModelSerializer):
    orders = serializers.IntegerField(read_only=True, source='num_orders')

    class Meta:
        model = Article
        fields = '__all__'

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


Note: The related_name=… parameter [Django-doc]
is the name of the relation in reverse, so from the User model to the Order
model in this case. Therefore it (often) makes not much sense to name it the
same as the forward relation. You thus might want to consider renaming the ordersauthor relation to orders.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading