I am doing CRUD project with foreign keys and I am using serializers.I want to get the Name of the categories,sub categories,color and size instead of thier IDs serializer:
class POLLSerializer(serializers.ModelSerializer): class Meta: model = Products fields = "__all__"
models are:
class Products(models.Model): categories = models.ForeignKey(Categories,on_delete=models.CASCADE) sub_categories = models.ForeignKey(SUBCategories,on_delete=models.CASCADE) color = models.ForeignKey(Colors,on_delete=models.CASCADE) size = models.ForeignKey(Size,on_delete=models.CASCADE) # image = models.ImageField(upload_to = 'media/',width_field=None,height_field=None,null=True) title = models.CharField(max_length=50) price = models.CharField(max_length=10) sku_number = models.CharField(max_length=10) product_details = models.CharField(max_length=300) quantity = models.IntegerField(default=0) isactive = models.BooleanField(default=True) class Categories(models.Model): #made changes to category_name for null and blank category_name = models.CharField(max_length=20) category_description = models.CharField(max_length=20) isactive = models.BooleanField(default=True) class Colors(models.Model): color_name = models.CharField(max_length=10) color_description = models.CharField(max_length=10) isactive = models.BooleanField(default=True) class Size(models.Model): size_name = models.CharField(max_length=10) size_description = models.CharField(max_length=20) isactive = models.BooleanField(default=True) class SUBCategories(models.Model): category_name = models.ForeignKey(Categories, on_delete=models.CASCADE) sub_categories_name = models.CharField(max_length=20) sub_categories_description = models.CharField(max_length=20) isactive = models.BooleanField(default=True)
<td>Categories</td> <td> <select name="categories" id=""> {% for c in context %} <option value="{{c.id}}">{{c.category_name}}</option> {% endfor %} </select> </td> <td>Sub-Categories</td> <td> <select name="sub_categories" id=""> {% for c in sub_context %} <option value="{{c.id}}">{{c.sub_categories_name}}</option> {% endfor %} </select> </td> <td>Colors</td> <td> <select name="color" id=""> {% for c in color_context %} <option value="{{c.id}}">{{c.color_name}}</option> {% endfor %} </select> </td> <td>Size</td> <td> <select name="size" id=""> {% for c in size_context %} <option value="{{c.id}}">{{c.size_name}}</option> {% endfor %} </select> </td>
below is the insert function
def insert(request): data = {} if request.method == "POST": print('POST',id) data['categories'] = request.POST.get('categories') data['sub_categories'] = request.POST.get('sub_categories') data['color'] = request.POST.get('color') data['size'] = request.POST.get('size') data['title'] = request.POST.get('title') data['price'] = request.POST.get('price') data['sku_number'] = request.POST.get('sku_number') data['product_details'] = request.POST.get('product_details') data['quantity'] = request.POST.get('quantity') form = POLLSerializer(data=data) print(form) if form.is_valid(): print('form after valid:',form) print("error of form:",form.errors) form.save() messages.success(request, "Record Updated Successfully...!:)") return redirect("polls:show") else: print('form not valid') print(form.errors) if request.method == "GET": print('POST',id) category_dict = Categories.objects.filter(isactive=True) category = CategoriesSerializer(category_dict, many=True) sub_category_dict = SUBCategories.objects.filter(isactive=True) sub_category = SUBCategoriesSerializer(sub_category_dict,many=True) color_dict = Colors.objects.filter(isactive=True) color = ColorsSerializer(color_dict,many=True) size_dict = Size.objects.filter(isactive=True) size = SizeSerializer(size_dict,many=True) hm = {"context": category.data,"sub_context":sub_category.data,"color_context":color.data,"size_context":size.data} return render(request, "polls/product_insert.html", hm)
show function
def show(request): showall = Products.objects.filter(isactive=True) print("show all data:",showall) serializer = POLLSerializer(showall,many=True) return render(request,'polls/product_list.html',{"data":serializer.data})
instead of name of categories subcategories color size etc I am getting id below is how the product_insert looks on webpage
where is the problem here?
Advertisement
Answer
You need to specify in the serializer that you want the foreign keys to be displayed as strings:
from rest_framework import serializers class POLLSerializer(serializers.ModelSerializer): categories = serializers.StringRelatedField(many=False) sub_categories = serializers.StringRelatedField(many=False) color = serializers.StringRelatedField(many=False) size = serializers.StringRelatedField(many=False) class Meta: model = Products fields = "__all__"
This displays whatever is returned by the __str__
method of the object, which you can override to return its name.
class Categories(models.Model): category_name = models.CharField(max_length=20) category_description = models.CharField(max_length=20) isactive = models.BooleanField(default=True) def __str_(self): return self.category_name class Colors(models.Model): color_name = models.CharField(max_length=10) color_description = models.CharField(max_length=10) isactive = models.BooleanField(default=True) def __str_(self): return self.color_name class Size(models.Model): size_name = models.CharField(max_length=10) size_description = models.CharField(max_length=20) isactive = models.BooleanField(default=True) def __str_(self): return self.size_name class SUBCategories(models.Model): category_name = models.ForeignKey(Categories, on_delete=models.CASCADE) sub_categories_name = models.CharField(max_length=20) sub_categories_description = models.CharField(max_length=20) isactive = models.BooleanField(default=True) def __str_(slef): return self.category_name
Alternative
If you do not want to touch your serializer (StringRelatedField
is read-only, which may mean there are certain operations you cannot do, like POST
), you can always add extra parameters to your serialized data by doing something like this:
def show(request): showall = Products.objects.filter(isactive=True) print("show all data:",showall) serializer = POLLSerializer(showall,many=True) data = serializer.data for i in range(len(data)): product = Products.objects.filter(id=data[i]['id']).first() data[i]['category_display_name'] = product.categories.__str__() data[i]['color_display_name'] = product.color.__str__() data[i]['size_display_name'] = product.size.__str__() data[i]['sub_category_display_name'] = product.sub_categories.__str__() return render(request,'polls/product_list.html',{"data":data})
Then, you can simply use the category_display_name
, color_display_name
, size_display_name
and sub_category_display_name
to render your table in the template (of course, you need to define the __str__
methods of the Categories
, Colors
, Size
and SUBCategories
models here too). This may lead to performance issues when working with large databases, though, so not really recommended…