1

I would like to make a simple lazy loading with Django Rest Framework. I have a solid background with Laravel where you can simply use it like so:

Subscription::with('company')->paginate()

But with DRF I'm having problems. One Company can have one subscription and my models are defined as such:

Company

class CompanyManager(BaseUserManager):
    def create_user(self, email, password=None):
        """
        Creates and saves a User with the given email and password
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
        )

        user.set_password(password)

        user.save(using=self._db)

        return user


class Company(AbstractBaseUser):
    """
        Company refers to what we have referee in the official document as "Empresa Partner"

        Attributes:
            name: The name of the main company
            email: Email to contact the main company
            code: the code attributed to this company
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    email = models.EmailField(unique=True)
    username = models.CharField(blank=True, max_length=100)
    is_staff = models.BooleanField(blank=True, default=False)
    our_system_date = models.DateTimeField(auto_now=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CompanyManager()

    def __str__(self):
        return self.email

Subscription

class Subscription(models.Model):
    """
    Subscriptions that references the plans and the companies
    :company:
        The owner of this subscription

    :plan:
        The plan this subscription is based on

    :starts:
        When the subscription starts

    :ends:
        When this subscription ends
    """
    company = models.ForeignKey(Company, on_delete=models.CASCADE)
    plan = models.ForeignKey(Plan, on_delete=models.CASCADE)
    starts = models.DateTimeField()
    ends = models.DateTimeField()
    created_at = models.DateTimeField(auto_now=True)

I have tried using select_related referred by this answer What's the difference between select_related and prefetch_related in Django ORM? but every time I make a request to the endpoint it doesn't show the related Company of the Subscription

How I'm using select_related:

    def list(self, request, *args, **kwargs):
        queryset = Subscription.objects\
            .all().select_related('company')\
            .order_by('-created_at')
        page = self.paginate_queryset(queryset)

        if page is not None:
            serializer = SubscriptionSerializer(
                page,
                many=True,
            )

            return self.get_paginated_response(serializer.data)

In my SubscriptionSerliazer:

class SubscriptionSerializer(ModelSerializer):
    class Meta:
        model = Subscription
        fields = (
            'company',
            'plan',
            'starts',
            'ends',
            'created_at',
        )
Bruno Francisco
  • 3,841
  • 4
  • 31
  • 61
  • I think this is more realating to Django than DRF, and in django, all query set is lazy by default. - [Queryset are lazy](https://docs.djangoproject.com/en/2.1/topics/db/queries/#querysets-are-lazy) – tim Mar 28 '19 at 08:45
  • I'm fairly new to Django/DRF and I'm trying to make the relationship between Django/DRF concepts and Laravel concepts. My problem here may seem in the SubscriptionSerialization for some reason (at least that's my understanding). That is why the DRF tag – Bruno Francisco Mar 28 '19 at 08:47
  • 1
    https://www.django-rest-framework.org/api-guide/relations/ also seems would be interesting for you https://www.django-rest-framework.org/api-guide/pagination/ – iklinac Mar 28 '19 at 08:53
  • 1
    @iklinac Thank you so much. I thought DRF understood the relationships of Django and there was no need to define them. Thank you for the link and after reading it it solved my problem – Bruno Francisco Mar 28 '19 at 08:59

1 Answers1

1

If you want to return the fields of a related model rather than just its primary key, you need to define a serializer for the related model (here: CompanySerializer) and direct the parent serializer to use it:

class SubscriptionSerializer(ModelSerializer):
    company = CompanySerializer()

    class Meta:
        model = Subscription
        fields = (
            'company',
            # ...
        )
Endre Both
  • 5,540
  • 1
  • 26
  • 31
  • Thank you Endre. As stated in my comments I thought DRF understood the relationship that came with Django and there was no need to "serialize" them. Thank you – Bruno Francisco Mar 28 '19 at 09:01