Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework: Order by Serializer Method Field

I am currently using Django REST framework 3.11.0 with Django 3.0.6. I am still very new to DRF and I am not sure how to approach this problem. I am trying to apply sort to SerializerMethodField and an enum. I was able to find some documentation that states that I could make my own OrderFilter but I dont know how. Are there any examples I could use? Here is my code.

View

from rest_framework import generics
from V1.assets.models.asset_main import Asset
from V1.assets.serializers.asset_serializer import AssetSerializer
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend

class AssetsView(generics.ListCreateAPIView):
    queryset = Asset.objects.all()
    serializer_class = AssetSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filter_fields = ['asset_type']
    search_fields = ['asset_type', 'asset_properties', 'current_employee_name'] 

Model

class AssetType(models.TextChoices):
    LAPTOP = 'LPT', _('Laptop')
    MOUSE = 'MSE', _('Mouse')
    MONITOR = 'MTR', _('Monitor')
    AC_ADAPTER = 'ADR', _('AC Adapter')
    TELEPHONE = 'TLP', _('Telephone')
    LOCK = 'LCK', _('Lock')
    HEADSET = 'HDS', _('Headset')

class Asset(CreatedModified):

    asset_type = models.CharField(
        max_length=3,
        choices=AssetType.choices,
        default=None
    )
    asset_properties = JSONField(default=dict)
    current_employee = models.ForeignKey(
        Employee,
        related_name='assets_current_employees', 
        related_query_name='assets_current_employee',
        default=None,
        on_delete=models.CASCADE,
        null=True,
        blank=True
    )

    class Meta:
        app_label = 'assets'
        default_related_name = 'assets'

    def __str__(self):
        return self.asset_type

Serializer

from V1.general.enums import AssetStatus, AssetType
from V1.accounts.models.employee_main import Employee

class AssetSerializer(serializers.ModelSerializer):

    current_employee_name = serializers.SerializerMethodField('get_full_name_from_employee')
    asset_type = serializers.CharField(source='get_asset_type_display')

    class Meta:
        model = Asset
        fields = (
            'id',
            'asset_type',
            'asset_properties',
            'current_employee',
            'current_employee_name'
        )
        extra_kwargs = {
            'asset_type': {
                'required': True, 
                'allow_blank': False
            }
        }

    def get_full_name_from_employee(self, asset):
        current_employee_name = asset.current_employee.first_name + ' ' + asset.current_employee.last_name
        return current_employee_name

I can't seem to order by current_employee_name or asset_type. What should I do to allow sorting for these two fields?

like image 365
Vince Orio Avatar asked Aug 16 '26 23:08

Vince Orio


1 Answers

As far as I can understand from your question you want to order the Assets by the current employee name. Let's take few names for example:

  • Jean d'Artagnan (first_name: Jean, last_name: d'Artagnan)
  • Joe Plumber (first_name: Joe, last_name: Plumber)
  • Jonas Meyer (first_name: Jonas, last_name: Meyer)

The same ordering can be achieved if we sort first by first_name and then by last_name. In case there are multiple entries with the same first_name the ordering will be done be the last_name.

To achieve this you can simply specify the ordering_fields in your view:

class AssetsView(generics.ListCreateAPIView):
    filters = [filters.OrderingFilter]
    ordering_fields = ['current_employee.first_name', 'current_employee.last_name']
like image 113
cezar Avatar answered Aug 19 '26 00:08

cezar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!