1

I have built a project with a React frontend and a Django Rest Framework (DRF) API for my backend. Things are going well but I am quite curious about best practices for data saved against your models.

As an example, I have a user model with first_name and last_name fields. There is a one-to-one relationship between my user and the two user domains (let's say Buyer and Seller as an example). In addition, we have a foreign key relationship for Seller on something like a Product.

On my UI, I have tables that display the data and in general, the majority of tables display the user's full name (first_name + last_name).

Generally, all table fields I will want to filter by and order by via API (eg. {base_url}/product/?ordering=full_name).

I decided that I wanted the data returned from the REST API to represent the table data so I am now returning full_name by augmenting the serializer of Buyer and Seller to have full name using a SerializerMethodField like so:

full_name = serializers.SerializerMethodField()


...


def get_full_name(self, obj) -> str:
    return obj.user.get_full_name()

However, I will also need to do this in all places where I want to show the Buyer/Seller where they are referenced by a Foreign Key.

So let's say we need it in the Product, I would have something like:

seller_first_name = serializers.CharField(source='seller.user.first_name')
seller_last_name = serializers.CharField(source='seller.user.last_name')
seller_full_name = serializers.SerializerMethodField()

...


def get_seller_full_name(self, obj) -> str:
    return obj.seller.user.get_full_name()

I guess I'm curious if it would be best to store all of these fields directly on the user object (first_name, last_name, and full_name). There is clearly some duplication here, so I assume Django would have a way for me to auto-write full_name based on first_name and last_name without requiring it to be passed in the API.

I'm sure it can be done either way but this is my first project using DRF as a backend and I would rather hear some other's experience now rather than learn myself in a year and have to do a large refactoring later on.

Thanks for any advice in advance.

All the best,

Brandon

Brandon Shute
  • 93
  • 1
  • 8
  • You don't need to duplicate that data (Why would you?) About repeating it everywhere, why don't you just [nest](https://www.django-rest-framework.org/api-guide/relations/#nested-relationships) the user serializer or use a [mixin](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful)? – Abdul Aziz Barkat Nov 22 '21 at 16:28
  • I have considered going down this road, currently, I'm using default filter sets and ordering. If I do nest the user, will I be able to filter the data through the URL like: `{base_url}/product/?ordering=full_name`? @AbdulAzizBarkat The reason I ask is that the table loads data with pagination (limit and offset) so the filtering and ordering needs to be done through the API. I can definitely do more research on Mixins, thank you for the suggestion! – Brandon Shute Nov 22 '21 at 16:35

1 Answers1

0

You can define a property in your model:

class YourModel(models.Model):

...

@property
def full_name(self):
    return f'{self.first_name} {self.last_name}'

Then you can access this in any serializer using source keyword argument:

full_name = serializers.CharField(source='YourModel.full_name')

Here's the doc

Pooya Kamranjam
  • 355
  • 3
  • 9
  • The property looks nice but I don't think I can filter and order by a property in Django right (or at least via API) like `{base_url}/product/?ordering=full_name` If this is possible, then that's perfect but my understanding was it has to be a DB field to filter and order from a table – Brandon Shute Nov 22 '21 at 23:28