How to get the nested objects in DRF

I have two models Role and User. User model has a foreign-key field associated with model Role.

Model Role

class Role(models.Model):
    
    role_name = models.CharField(max_length=255, blank=False, unique=True)

    def __str__(self):

        return 'Role Object ({})'.format(self.id, self.role_name)

Model User

class User(AbstractBaseUser, PermissionsMixin):
    
    first_name = models.CharField(max_length=255, blank=False)
    last_name = models.CharField(max_length=255, blank=False)
    email = models.EmailField(max_length=255, blank=False, unique= True)
    phone_number = models.BigIntegerField(blank=False, unique= True)
    password = models.TextField(blank=False)
    company_name = models.CharField(max_length=255, null=True, unique=True)
    is_active = models.BooleanField(default= False)
    role = models.ForeignKey(Role, related_name='group_name', on_delete=models.CASCADE, blank=False)
    business = models.ForeignKey(Businesses, on_delete=models.CASCADE, null=True)

    objects = UserManager()

    USERNAME_FIELD = 'email'

    def __str__(self):

        return 'User Object ({})'.format(self.id)

Using ModelSerializer and ListAPIView I want to get the list of all the users as shown below –

{
    "first_name": "",
    "last_name":"",
    "email":"",
    "phone_number":,
    "is_active":"",
    "role":{
            "id":1,
            "role_name": "Admin"
           }
}

Also, I have created serializers –

class AdminSerializer(serializers.ModelSerializer):

    role = RoleSerializer(read_only=True)

    class Meta:
        model = User
        fields = ['id', 'first_name', 'last_name', 'email', 'phone_number', 'password', 'role', 'is_active' ]
        read_only_field = ['role_name']
        extra_kwargs = {
            'password':{
                'write_only':True
            },
            'is_active':{
                'required':False
            }
        }

    def create(self, validated_data):

        return User.objects.create_user(**validated_data)


class RoleSerializer(serializers.ModelSerializer):

    class Meta:
        model = Role
        field = ['id', 'role_name']

What exactly should I do to my serializer to achieve desire output. What exactly should I write in my ListAPIView() what a ListAPIVIew returns.

class UsersListAPIView(ListAPIView):

    def get(self, request, format=None):

        serializer_class = AdminSerializer

        def get_queryset(self):

            return User.objects.filter(role=request.query_param.get['id']).prefetch_related("group_name")
        
        return Response (self.get_queryset())

This returns an error –

AssertionError: 'UsersListAPIView' should either include a `queryset` attribute, or override the `get_queryset()` method.

Go to Source
Author: Jeet Patel

How can I link an object on save in django to an existing one if there is a matching value between them?

I’m using Django and DRF to to reconcile two lists of data (promises to pay, and payments). When uploading new payments, if the payment transaction ID shares the same ID as a promise to pay, I want to link them by saving the corresponding promise in the payment’s foreign key field.

I have two models:

class Promise(models.Model):
     transaction_id = models.CharField(max_length=50)
     amount_promised = models.DecimalField(decimal_places=2, max_digits=8)
     created_on = models.DateTimeField(auto_now_add=True)

class Payment(models.Model):
    promise = models.OneToOneField(Promise, on_delete=models.CASCADE, blank=True)
    transaction_id = models.CharField(max_length=50)
    amount_paid = models.DecimalField(decimal_places=2, max_digits=8)
    created_on = models.DateTimeField(auto_now_add=True)

and two views:

class PromiseViewSet(viewsets.ModelViewSet):
    permission_classes = (IsCreatorOrReadOnly,)
    queryset = Promise.objects.all()
    serializer_class = PromiseSerializer

class PaymentViewSet(viewsets.ModelViewSet):
    permission_classes = (IsCreatorOrReadOnly,)
    queryset = Payment.objects.all()
    serializer_class = PaymentSerializer

My understanding is this requires a custom save method, but I’m not certain if the magic should be happening in views or models. Either way, the logic should be something like:

  • Loop through promises…if the new payment.transaction_id = a promise.transaction_id, break and link the two together by saving the promise.pk to the promise foreign key in the newly created payment object.

And the solution would look something like this:

warning, this is rough!

def save(self, *args, **kwargs):
    
    #check if promise ID was manually entered, if not continue
    if self.promise is None:
        for transaction_id in Promise.transaction_id:

            if transaction_id = self.transaction_id:
                return Promise.pk
                self.promise = Promise.pk  

    else:
        .save()

    super(Payment, self).save(*args, **kwargs)

Go to Source
Author: Mike