'Adding to manytomany field, on added field from form

I have a model, that needs a user(ForeignKey), and a category(M2M), and for the category field in form, I extended its functionality by adding custom field to it(data-list but with input too), but I am unable to save the form with the category and user.

models.py

from django.contrib.auth.models import AbstractUser
from django.db import models


class User(AbstractUser):
    pass

class Category(models.Model):
    name = models.CharField(max_length=20, blank=True)

class Listings(models.Model):
    title = models.CharField(max_length=64, null=False, blank=False)
    description = models.CharField(max_length=64, blank=True)
    bid = models.IntegerField(null=False, blank=False)
    timestamp = models.DateField(db_index=True, auto_now_add=True)
    image_url = models.URLField(blank=True)
    category = models.ManyToManyField(Category)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        ordering=['timestamp', 'title']

forms.py

from auctions.models import Listings
from django import forms

class ListTextWidget(forms.TextInput):
    def __init__(self, data_list, name, *args, **kwargs):
        super(ListTextWidget,self).__init__(*args, **kwargs)
        self._name = name
        self._list = data_list
        self.attrs.update({
            'list':'list__%s' % self._name,
            'class':'form-control'
            })
    
    def render(self, name, value, attrs=None, renderer=None):
        text_html = super(ListTextWidget, self).render(name, value, attrs=attrs)
        data_list = '<datalist id="list__%s">' % self._name
        for item in self._list:
            data_list += '<option value="%s">' % item
        data_list += '</datalist>'

        return (text_html + data_list)


class ListingsForm(forms.ModelForm):
    category = forms.CharField()

    class Meta:
        model = Listings
        fields = ['title', 'description', 'bid', 'image_url', 'category']
        widgets = {
            'title': forms.TextInput(attrs={'class':'form-control'}),
            'description': forms.TextInput(attrs={'class':'form-control'}),
            'bid': forms.TextInput(attrs={'class':'form-control'}),
            'image_url': forms.TextInput(attrs={'class':'form-control'}),
            'category': forms.TextInput(attrs={'class':'form-control'})
        }
    def __init__(self, *args, **kwargs):
        _category_list = kwargs.pop('data_list', None)
        super(ListingsForm, self).__init__(*args, **kwargs)
    
        self.fields['category'].widget = ListTextWidget(data_list=_category_list, name='category-list')

views.py

def create_listings(request):
    if request.method == "POST":
        form = ListingsForm(request.POST)
        if form.is_valid():
            #**what to do to save category and user**
            return redirect(reverse('index'))
    else:
        category_list = Category.objects.all().values_list('name')
        form = ListingsForm(data_list=category_list)   
    return render(request, 'auctions/create_listings.html', {
        'form': form
    })

How do I save all the data into a new Listing, during the form.save()?

I have tries using commit=False, but I get ValueError:Field 'id' expected a number but got 'o'. Is there I way I can save all at once, or do I have to create a Listing, then manually add the remaining data after?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source