Reputation: 1199
In my django app, i have four model tables linked using foreign keys, the problem is, when i make a query for any model table, the fields that are linked through foreign keys are returned as id's instead of the name.
My way does not work.
My customers models.py file
1st model
class Customer(models.Model):
name = models.CharField(max_length=50)
phone = models.CharField(max_length=20, unique=True)
email = models.EmailField(max_length=255, unique=True, blank=True)
image = models.ImageField(default='default.png', upload_to='customer_photos/%Y/%m/%d/')
data_added = models.DateField(default=datetime.now, blank=True)
def __str__(self):
return self.name
2nd model
class ShippingAddress(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="customer_ship_address")
description = models.TextField(blank=True)
frequent_customer = models.BooleanField(default=False)
address = models.CharField(max_length=50, blank=True)
zip_code = models.CharField(max_length=12, blank=True)
location = models.CharField(max_length=255)
def __str__(self):
return self.customer.name
3rd model - PaymentInvoice
class paymentInvoice(models.Model):
shipping_address_owner = models.ForeignKey(
ShippingAddress, on_delete=models.CASCADE, related_name="customer_invoice")
product = models.ManyToManyField(
Product, related_name='product_invoice')
mode = models.CharField(max_length=20, choices=paymentMode.choices, default=paymentMode.MPESA)
date = models.DateField(default=datetime.now)
invoice_id = models.CharField(
max_length=50, unique=True, default=increment_invoice_number)
quantity = models.PositiveSmallIntegerField()
status = models.CharField(
max_length=20, choices=paymentStatus.choices, default=paymentStatus.PENDING)
payment_made = models.DecimalField(max_digits=20, decimal_places=2)
def __str__(self):
return self.shipping_address_owner.customer.name
My Products models.py file
class Product(models.Model):
slug = models.CharField(max_length=200, unique=True)
name = models.CharField(max_length=200)
available = models.BooleanField(default=True)
description = models.TextField(blank=True)
image = models.ImageField(default='default_product.jpg', upload_to='product_photos')
category = models.CharField(max_length=200)
qty_amount = models.CharField(
max_length=20, choices=Qty_Choices, default='250ml')
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.name
My PaymentInvoice views.py file
class paymentInvoiceListCreateView(ListCreateAPIView):
"""
ListCreateAPIView executes both 'GET' and 'POST' requests. i.e listing a queryset or creating a model instance.
"""
serializer_class = paymentInvoiceSerializer
queryset = paymentInvoice.objects.all().order_by(
'-date').values(shipping_address_owner__customer)
When i make the above query the api returns the following, where the product field and shipping_address_owner field are just id's. I need there respective names instead.
{
"count": 6,
"next": null,
"previous": null,
"results": [
{
"id": 9,
"mode": "Mpesa",
"date": "2020-07-27",
"invoice_id": "INV-0006",
"quantity": 1,
"status": "Pending",
"payment_made": "500.00",
"shipping_address_owner": 9,
"product": [
1
]
},
EDIT: paymentInvoiceSerializer
class paymentInvoiceSerializer(serializers.ModelSerializer):
class Meta:
model = paymentInvoice
fields = '__all__'
Upvotes: 1
Views: 2071
Reputation: 7330
You can try like this in your serializer.
class paymentInvoiceSerializer(serializers.ModelSerializer):
shipping_address_owner = serializers.CharField(source='shipping_address_owner.customer')
class Meta:
model = paymentInvoice
fields = ['shipping_address_owner',...]
Upvotes: 1
Reputation: 4208
You need to make some changes to your serializer.
If you just need the name and nothing more:
class paymentInvoiceSerializer(serializers.ModelSerializer):
product = serializers.SerializerMethodField()
shipping_address_owner = serializers.SerializerMethodField()
class Meta:
model = paymentInvoice
fields = '__all__'
def get_product(self, instance):
names = []
for product in instance.product.all():
names.append(product.name)
return names
def get_shipping_address_owner(self, instance):
return instance.shipping_address_owner.customer.name
You can also create different serializer for each model and pass them to their fields to get the full serialized data for them. It would be something like this:
ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
And then in your payment serializer:
class paymentInvoiceSerializer(serializers.ModelSerializer):
product = ProductSerializer()
class Meta:
model = paymentInvoice
fields = '__all__'
You can do the same for shipping_address_owner
.
Upvotes: 1