pythondjangoformsmodelchoicefield

Django ModelFieldChoice select passing value


Hi i'm using ModelFieldChoice to set the foreign key from Provider in the model "Article" (Article belongs to Provider). The select in the template is displayed correctly with all the providers from the database, but when i try to post the form, it throws an error that the select value is required even if i'm passing it. Also i seted values for the article in the database, and when i tried to edit it, all the fields in the form are populated with the correct data except for the select. These are my models, i would appreciate the help, thanks! Sorry if i'm doing something wrong, this is my first time posting in stackoverflow. Article.py Model

class Article(models.Model):
     codigo = models.CharField(max_length=100, verbose_name='Codigo')
     proveedor = models.ForeignKey(Provider, on_delete=models.CASCADE)
     descripcion = models.CharField(max_length=200, verbose_name='Descripcion',null=False, blank=True)
     marca = models.CharField(max_length=100, verbose_name='Marca',null=True, blank=True)
     rubro = models.CharField(max_length=100, verbose_name='Rubro',null=True, blank=True)
     nota = models.TextField(verbose_name='Nota',null=True)
     costo = models.CharField(max_length=50, verbose_name='Costo',null=False, blank=True)
     created = models.DateTimeField(auto_now_add=True, verbose_name="Fecha de creación",null=True, blank=True)
     updated = models.DateTimeField(auto_now=True, verbose_name="Fecha de edición",null=True, blank=True)

class Meta:
    verbose_name = "articulo"
    verbose_name_plural = "articulos"
    ordering = ['-descripcion']

def __str__(self):
    return self.descripcion

Provider.py Model

class Provider(models.Model):
    razon_social = models.CharField(max_length=100, verbose_name='Razón Social', unique=True)
    direccion = models.CharField(max_length=100, verbose_name='Dirección', blank=True, null=True)
    localidad = models.CharField(max_length=100, verbose_name='Localidad', blank=True, null=True)
    provincia = models.CharField(max_length=100, verbose_name='Provincia', blank=True, null=True)
    telefono = models.CharField(max_length=100, verbose_name='Teléfono', blank=True, null=True)
    mail = models.CharField(max_length=100, verbose_name='Email', blank=True, null=True)
    web = models.CharField(max_length=100, verbose_name='Sitio Web', blank=True, null=True)
    created = models.DateTimeField(auto_now_add=True, verbose_name="Fecha de creación", null=True)
    updated = models.DateTimeField(auto_now=True, verbose_name="Fecha de edición", null=True)

    class Meta:
        verbose_name = "proveedor"
        verbose_name_plural = "proveedores"
        ordering = ['-razon_social']

    def __str__(self):
        return self.razon_social

form.py (ArticleCreate)

class ArticleCreate(forms.ModelForm):
    proveedor_id = forms.ModelChoiceField(queryset=Provider.objects.none(), empty_label="Elegir un proveedor")

    class Meta:
        model = Article
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(ArticleCreate, self).__init__(*args, **kwargs)
        self.fields['proveedor_id'].queryset = Provider.objects.all()

views.py

def add_article(request):
if request.method == 'POST':
    create = ArticleCreate(request.POST)
    print(request.POST['proveedor_id'])
    if create.is_valid():
        create.save()
        return redirect('/dashboard/articles/?add=success')
    else:
        print(create.errors)
        return redirect('/dashboard/articles/?error=True')
else:
    return render(request, "article/add_edit_article.html",  {'editMode': False,'form': ArticleCreate})

In views.py when i print 'proveedor_id' the value is correctly displayed in console but then the "is_valid()" fails and it prints the error "<ul class="errorlist"><li>proveedor<ul class="errorlist"><li>Este campo es obligatorio.</li></ul></li></ul>" (obligatory field, as if i'm not passing it)


Solution

  • First, simplify your ArticleCreate serializer to be like this:

    class ArticleCreate(forms.ModelForm):
      class Meta:
        model = Article
    

    Then in the request pass proveedor field, not proveedor_id. In Django/DRF you should pass association IDs using "{{association_name}}": id pattern, not "{{association_name}}_id": id

    Sou you can simplify your view as well:

    def add_article(request):
    if request.method == 'POST':
      create = ArticleCreate(request.POST)
      if create.is_valid():
        create.save()
      ...