Field 'mobile' expected a number but got ['2222222', '2222222']

Question:

This is Error showing

TypeError at /page
Field 'mobile' expected a number but got ['22222', '3333'].
Request Method: POST
Request URL:    http://127.0.0.1:8000/page
Django Version: 4.1
Exception Type: TypeError
Exception Value:    
Field 'mobile' expected a number but got ['22222', '3333'].

While Submitting Form This error occurs.
I am trying to submit form of same name twice simultaneously to same model

Views.py

def page(request):

    if request.method == 'POST':
        description = request.POST['description']
        price = request.POST['price']
        name = request.POST.getlist('name')
        mobile = request.POST.getlist('mobile')

        pay = bill(description=description,price=price)
        pay.save()

        
        mypayee = payee(billId=pay,name=name,mobile=mobile)
        mypayee.save()

    return render(request, 'split_app/page.html')

this model

from django.db import models

# Create your models here.
class bill(models.Model):
    price = models.IntegerField()
    description = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.description
        
class payee(models.Model):
    billId = models.ForeignKey(bill,on_delete=models.CASCADE,related_name='persons')
    name = models.CharField(max_length=50)
    mobile = models.IntegerField()

this is image of HTML FORM generated using javascript
enter image description here

** This is how I am submitting data with form having same form twice of same name(name & mobile) **

HTML generate

<div class="container my-3">
        <button type="button" class="btn btn-secondary">ADD NEW BILL</button>
        <form action="/page" method="POST">
            {% csrf_token %}
            <div class="input-group mb-3">
                <label for="discription" class="col-sm-2 col-form-label">DESCRIPTION:</label>
                <div class="col-sm-2">
                    <input type="text" name="description" id="discription" placeholder="Bill For.." />
                </div>
            </div>
            <div class="input-group mb-3">
                <label for="price" class="col-sm-2 col-form-label">BILL PRICE:</label>
                <div class="col-sm-2">
                    <input type="number" name="price" id="price" title="only numbers allowed"
                        placeholder="&#x20B9" />
                </div>
            </div>
            <div class="mb-3 row">
                <label for="person" class="col-sm-2 col-form-label">SPLIT IN:</label>
                <div class="col-sm-10">

                    <button type="button" class="btn btn-info" onclick="increment()">+</button>
                    <button type="button" class="btn btn-info" id="payeesbtn">ADD PAYEE:</button>
                    <button type="button" class="btn btn-info" onclick="decrement()">-</button>

                    <div class="container my-3" id="addpayees"></div>
                    
                </div>
            </div>
            <button type="submit" class="btn btn-info">Save</button>
        </form>
    </div>

Javascript

let x = 1;
function increment() {
        
    const div = document.createElement('div');
    div.className = 'container my-3';
    div.idName = 'x';

    
    div.innerHTML = `<h5>payee ${x}</h5>
                        <table>
                            <tr>
                                <th>Name:</th>
                                <td><input type="text" name="name"></td>
                            </tr>
                            <tr>
                                <th>Mobile:</th>
                                <td><input type="number" name="mobile"></td>
                            </tr>
                        </table>
                        <input type="button" value="-" onclick="decrement(this)" />
                        <button type="button" class="btn btn-info" onclick="decrement(this)">-</button>`;

    document.getElementById("addpayees").appendChild(div);
      
    x++;
};
Asked By: Shamshad z

||

Answers:

The payee.mobile field is defined as an IntegerField, but in your view function you are calling:

mobile = request.POST.getlist('mobile')

which produces a list of values. Then you do this:

mypayee = payee(billId=pay,name=name,mobile=mobile)

That is what the error tells you. You are trying to create a payee instance and assign a list to the integer field.

PS:

If you want to create two separate instances of payee with both those values ['22222', '3333'], you need to do something like:

mypayee1 = payee(billId=pay,name=int(name[0]),mobile=int(mobile[0]))
mypayee2 = payee(billId=pay,name=int(name[1]),mobile=int(mobile[1]))

But I am just guessing here.

PPS:

If the size of the name and mobile lists is dynamic, you could loop over them. You did not provide a lot of context, but I assume that those query parameters in the POST request will have the same number of items, i.e. the lists will be of the same size. Then you could do something like this:

def page(request):
    ...
    names = request.POST.getlist('name')
    mobiles = request.POST.getlist('mobile')
    pay = bill(description=description,price=price)
    pay.save()
    for name, mobile in zip(names, mobiles):
        mypayee = payee(billId=pay,name=name,mobile=int(mobile))
        mypayee.save()

If you don’t care about the pre_save and post_save signals, you could create them in bulk like this: (check the docs for caveats!)

def page(request):
    ...
    names = request.POST.getlist('name')
    mobiles = request.POST.getlist('mobile')
    pay = bill(description=description,price=price)
    pay.save()
    payee.objects.bulk_create([
        payee(billId=pay,name=name,mobile=int(mobile))
        for name, mobile in zip(names, mobiles)
    ])

Either way, at this point I would strongly suggest wrapping the entire affair in a transaction to ensure data integrity.

Answered By: Daniil Fajnberg
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.