Nested model

Nested model

Demonstrates a nested serializer: the User model has a foreign key to Company, and UserSerializer embeds CompanySerializer. Both name fields stream to the client through a single rx.model declaration.

Backend

from rxdjango import ContextChannel, rx, action
from .models import User
from .serializers import UserSerializer


class NestedModelChannel(ContextChannel):

    user = rx.model(UserSerializer())

    @action
    async def authorize(self, password: str):
        if password == 'password':
            self.user = await User.objects.select_related('company').aget(id=1)
            return True
        return False

Models

from django.db import models


class Company(models.Model):
    name = models.CharField(max_length=64)


class User(models.Model):
    name = models.CharField(max_length=32)
    company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='users')

Serializers

from rest_framework import serializers
from nested_model.models import Company, User


class CompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = ['id', 'name']


class UserSerializer(serializers.ModelSerializer):
    company = CompanySerializer()

    class Meta:
        model = User
        fields = ['id', 'name', 'company']

Frontend

import React, { useState } from 'react';
import { useChannel } from '@rxdjango/react';
import { NestedModelChannel } from '../../rx/nested_model/nested_model.channels';
import {
  Sections,
  Button,
  TextInput,
  Row,
  Note,
} from '../../components/demo';

export function NestedModelDemo() {
  const channel = useChannel(NestedModelChannel);
  const [password, setPassword] = useState('password');

  return (
    <Sections>
      <div>
        <Note>
          Authorize with a password to load the user model along with its nested company.
        </Note>
        <Row>
          <TextInput
            id="nested-model-password"
            label="Password"
            value={password}
            onChange={setPassword}
          />
          <Button
            variant="secondary"
            onClick={() => channel.authorize(password)}
          >
            Authorize
          </Button>
        </Row>
      </div>
      <div>
        {channel.user ? (
          <p>
            You are user "{channel.user.name}" at "
            {channel.user.company._loaded
              ? channel.user.company.name
              : 'Loading…'}"
          </p>
        ) : (
          <p>
            Enter your password
          </p>
        )}
      </div>
    </Sections>
  );
}

export default NestedModelDemo;