Really struggling with this and it seems like it should be really straight forward. Basically, I am just trying to the products associated with a user, and then the short_name
for each of those products to be rendered on the FE.
I have a table that has the user_id
and prod_id
. The table can look like this:
user_id | prod_id
-----------------
2 | 42
2 | 2
2 | 21
13 | 7
13 | 17
13 | 2
The user_id
is a models.ForeignKey
to the User
table and the prod_id
is a models.ForeignKey
to Products
table. Better yet, here is the model:
# ./home/models.py
from django.contrib.auth import get_user_model
from django.db import models
User = get_user_model()
class Product(models.Model):
id = models.AutoField(primary_key=True)
code = models.CharField(unique=True, max_length=16)
name = models.CharField(max_length=255, blank=True, null=True)
short_name = models.CharField(max_length=128)
updated = models.DateTimeField(blank=True, null=True)
created = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.short_name
class Meta:
db_table = 'Product'
class UserToProduct(models.Model):
user = models.ForeignKey(User, related_name='user_name', db_column='user_id', null=True)
prod = models.ForeignKey(Product, related_name='prod_name', db_column='prod_id', null=True)
class Meta:
db_table = 'User_to_Product'
unique_together = ('user', 'prod')
What should be happening is the React front-end sends the user_id
based on who is logged in to the Django/DRF back-end. This is happening just fine. Here is the related view:
# ./home/views.py
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST
from rest_framework.views import APIView
from .serializers import GetProductSerializer
from .models import Home
class GetHomeAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
serializer = GetProductSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
return Response(serializer.data, status=HTTP_200_OK)
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
From there, it should just be pulling the list of products related to them and then reading in the short_name
from the Product
model, or really just an object where I can parse out the short_name
.
Here is the serializer:
# ./home/serializers.py
from rest_framework.serializers import (
IntegerField,
ModelSerializer,
SerializerMethodField,
StringRelatedField,
)
from .models import *
class GetProductSerializer(ModelSerializer):
prod_name = StringRelatedField(many=True, required=False)
product = SerializerMethodField('get_products')
class Meta:
model = UserToProduct
fields = ('user', 'prod', 'prod_name')
def get_products(self, obj):
products = UserToProduct.objects.filter(user=data['user'])
return products
This particular variation results in: NameError: name 'data' is not defined
.
Change get_products()
to have:
# for testing reasons
products = UserToProduct.objects.filter(user=2)
This results in: KeyError: 'prod_name'
Anyway, I have spent more hours on this than I care to admit. This is some really basic stuff. I've tried dozens of variations. I'll keep working on it and posting what I've tried and the errors.
Also, this is the documentation I am referencing that I have read through dozens of times:
http://www.django-rest-framework.org/api-guide/relations/
http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/
Referenced countless other SO question/answers regarding this too and just not working.
EDIT: Probably have tried a few dozen more things and able to finally get a serialized response from the server; however, it isn't bringing in the short_name
. Only modifications I have made:
# ./home/models.py
class Product(models.Model)
...
users = models.ManyToManyField(User, through='UserToProduct')
# ./home/serializers.py
class GetProductSerializer(ModelSerializer):
user = IntegerField() # have to do this otherwise it returns the username and not the id
prod = SerializerMethodField()
class Meta:
model = UserToProduct
fields = [
'user',
'prod',
]
def get_prod(self, obj):
prod = UserToProduct.objects.filter(user=obj['user']).values('prod')
print(prod)
return prod
Also, important to note is just leaving the get_prod()
as:
prod = UserToProduct.objects.filter(user=obj['user'])
Results in a : TypeError: Object of type 'UserToProduct' is not JSON serializable
. However, it does list the short_name
in print(prod)
.