3👍
If you can add a package to you project, it would be easy with django-property-filter
Just convert your serializer code into a property like:
class Activity(BaseModel):
name = models.CharField(max_length=250)
last_execution = models.DateTimeField()
def __str__(self):
return self.name
class Meta:
ordering = ('name',)
@property
def next_execution(self):
# all your logic in comment can be pasted here
return self.last_execution + timedelta(hours=24)
Remove your SerializerMethodField()
and the def get_next_execution
from serializer
but keep it in fields list, this property will be listed as a field as well
class ActivitySerializer(serializers.ModelSerializer):
class Meta:
model = Activity
fields = ('id', 'name', 'last_execution', 'next_execution',)
Now, in the view, remove the filterset_fields
from your ViewSet
, we will add it in the FilterSet
class…
Create a FilterSet
to your ViewSet
from django_property_filter import PropertyFilterSet, PropertyDateFilter
class ActivityFilterSet(PropertyFilterSet):
next_execution = PropertyDateFilter(field_name='next_execution', lookup_expr='exact') # this is the @property that will be filtered as a DateFilter, you can change the variable name, just keep the `field_name` right
class Meta:
model = Activity
fields = { # here is the filterset_fields property
'id': ['exact'],
'name': ['icontains', 'exact'],
'last_execution': ['exact'],
}
And then, just add this FilterSet
to your ViewSet
and the magic happens
class ActivityViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = ActivitySerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = ActivityFilterSet
def get_object(self):
return super(ActivityViewSet, self).get_object()
def get_queryset(self):
return Activity.objects.all()
0👍
I really don’t like django-filter
– here is a method I prefer that gives us (almost) full access to the django-orm from the front end in a few lines of code:
class BaseViewSet(viewsets.ModelViewSet):
def get_queryset(self):
queryset = self.queryset
custom_filter = self.request.query_params.get('filter')
custom_exclude = self.request.query_params.get('exclude')
if custom_filter:
custom_filter = json.loads(custom_filter)
queryset = queryset.filter(**custom_filter)
if custom_exclude:
custom_exclude = json.loads(custom_exclude)
queryset = queryset.exclude(**custom_exclude)
return queryset
Now we can send requests like this:
// django-like filter:
var filter = {
last_execution : '2020-01-01 08:20:20'
}
$.ajax({
url : 'api/activities/?filter=' + JSON.stringify(filter)
type : 'GET',
success : function(response){...},
...
});
Essentially, your url now looks like:
https://mywebsite.com/api/activities/?filter={"last_execution":"2020-01-01 08:20:20"}
Now we can just add 24 hours to the last_execution_date
in our js code to retrieve the activity
(instead of doing this on the python side):
// can use libraries like moment.js etc:
var filter = {
last_execution : '2020-01-02 08:20:20'
}
$.ajax({...});
That’s it! No more adding fields to every – single – viewset.
- [Django]-Django crispy forms – Set hidden field value
- [Django]-Accessing join query results in SQLAlchemy
- [Django]-Opening a new browser tab invalidates Django's CSRF token, preventing form submission
- [Django]-Django – Slugify get lookup