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:
{
.....,
"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 theUsermodel [Django-doc] directly. For more information you can see the referencing theUsermodel section of the documentation.
Note: The
related_name=…parameter [Django-doc]
is the name of the relation in reverse, so from theUsermodel to theOrder
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 therelation toordersauthororders.