how to use input tag field instead default django?

Viewed 156

i'm trying to make an online order system. someone can order several items at the same time. for that reason i have used inlineformset and sometimes using {{form.field_name}} prevent some styles and js events , for that purpose i decided to use input fields manually <input> tags , i didnt faced such challenges in my previous projects. now im confused how to achieve it?

this is my models.py

class Item(models.Model):
     items = models.CharField(max_length=50)
     #others
     def __str__(self):
        return self.items 

class Invoice(models.Model):
     seller = models.ForeignKey(User,on_delete=models.CASCADE)
     customer = models.CharField(max_length=50)
     items = models.ManyToManyField(Item,through='ItemsInvoice')

class ItemsInvoice(models.Model):
     invoice= models.ForeignKey(Invoice,on_delete=models.CASCADE)
     item = models.ForeignKey(Item,on_delete=models.CASCADE)
     quantity = models.IntegerField()
     price = models.IntegerField()

i used function based view in view and this is my views.py

@login_required
def createClientInoiveView(request):
item_names = Item.objects.all()
if request.method == 'POST':
    customer = request.POST['customer']
    seller = request.user
    obj = CustomerInvoice.objects.create(seller=seller,customer=customer)        
    # inlineformset fields 
    item = request.POST['items']
    quantity = request.POST['quantity']
    price = request.POST['price']
    cash = request.POST['cash']
    discount = request.POST['discount']
    items = InvoiceItem.objects.create(item=item,quantity=quantity,price=price,cash=cash,discount=discount)
    
    with transaction.atomic():
        obj = obj.save(commit=False)
        if obj.is_valid and item.is_valid():
            item.invoice = obj
            obj.save()
            item.save()
            return redirect(reverse_lazy('invoiceapp:detail-invoice',kwargs={'pk':obj.pk}))

return render(request,'invoiceapp/create_invoice.html',{'item_names':item_names})

and this is my html form

<form method="POST">{% csrf_token %}
    {{items.management_form}}

    <div class="w-full  md:w-11/12 mx-auto realative p-2 bg-gray-200 wasll" style="direction: ltr !important;">
    
        <div class="p-1 pr-2 pb-1 text-xs border border-black rounded-lg flex flex-wrap">          
            <div class="flex w-8/12 lg:w-9/12">              
                <div class="w-10/12 ml-8 border-b border-gray-600 border-dotted">
                  <input type="text" name="customer" class="bg-transparent w-full text-right focus:outline-none" id="">
                </div>  
                <div class="">
                  :  name
                </div>
            </div>
        </div>
        <!-- table -->
        <div class="mt-1 border border-black">
            <!-- header -->
            <div class="flex flex-wrap grayBG text-sm text-white">                             
                <div class="w-16 md:w-1/12  border-r text-center">
                    price
                </div>
                <div class="w-16 md:w-2/12  border-r text-center">
                    quantity
                </div>
                <div class="w-20 md:w-2/12  border-r text-center">
                    items
                </div>
            
            </div>
            <!-- inputs -->
            <div id="allInp">
                <div class="flex flex-wrap grayBG text-sm text-black inp">

                    <div class="w-16 md:w-1/12 p-2 border-r text-center ">
                        <input type="number" name="price" onkeyup="totalSum()"  class="rounded-lg nrx focus:outline-none py-1 w-full">
                    </div>
                    <div class="w-16 md:w-2/12 p-2 border-r text-center ">
                        <input type="number" name="quantity" onkeyup="totalSum()"  class="rounded-lg focus:outline-none py-1 w-full">
                    </div>
                    <div class="w-20 md:w-2/12 p-2 border-r text-center">
                        <datalist id="types">
                            {% for i in item_names %}
                            <option value="{{i}}">
                            {% endfor %}
                          </datalist>
                        <input type="text" name="items" list="types" class="w-full rounded-lg focus:outline-none py-1">                    
                    </div>
                
                </div>
            </div>
        </div>
        
    </div>

    <div class="w-6/12 text-center mt-1 mx-auto mb-6">
        <button class="w-full bg-white text-gray-900" id="submit">submit</button>
    </div>
</form>
<script>
    $(function(){

        $('#allInp').formset({
            prefix:'{{items.prefix}}',
            addText:'add new row',
            addCssClass:'btn btn-info ',
            deleteText:'delete',
            deleteCssClass:'delFun',

        })  
  
</script>

but i keep getting this error message

Cannot assign "'mouse'": "ItemsInvoice.item" must be a "Item" instance.

and also these my forms.py

class CustomerInvoiceForm(forms.ModelForm):
    class Meta:
        model = Invoice
        fields = [
            'customer'
        ]

class CustomerInvoiceItemForm(forms.ModelForm):
item = forms.ModelChoiceField(queryset=Item.objects.all(),empty_label='---')
class Meta:
    model = ItemsInvoice
    fields = ['item','quantity','price']

CustomerInvoiceInlineFormset = inlineformset_factory(
     Invoice,ItemsInvoice,form=CustomerInvoiceItemForm,
     fields=('item','quantity','price'),extra=1
     )   

and also i have tried to use this

#other code

obj=CustomerInvoiceItemForm()
#instead of > CustomerInvoice.objects.create(seller=seller,customer=customer)
#other code
#and using this > items = CustomerInvoiceInlineFormset(request.POSt)
#instead of  > items = InvoiceItem.objects.create(item=item,quantity=quantity,price=price,cash=cash,discount=discount)

but saves nothing? isn't there something i should change in order to get what i trying for?

2 Answers

In template <option value="{{i}}"> outputs Ìtem.__str__ as the key and no Ìtem can be resolved from this.

Change to <option value="{{ i.pk }}">

The error means that you have to assign item instance object instead of the id string coming in the request.POST.
So in your views.py try the following:

item_id = request.POST['item']
item_instance = Items.objects.get(pk=int(item_id))

items = InvoiceItem.objects.create(item=item_instance,quantity=quantity,price=price,cash=cash,discount=discount)
Related