Home > Net >  Getting ID instead of Name in list
Getting ID instead of Name in list

Time:07-11

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 enter image description here

where is the problem here?

CodePudding user response:

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...

  • Related