Django динамически добавляет целочисленные поля в формы

Здравствуйте, у меня есть очень простое приложение, которое я делаю для того, чтобы изучить Django.

У меня есть таблица SQLite, в которой есть два столбца, первый - 'id', сгенерированный Django, второй - символьное поле, содержащее имя product_name.

Я пытаюсь заставить программу работать следующим образом:

  1. Получение списка значений в таблице. Этот набор_запросов присваивается bases
  2. Пройдитесь по каждому кортежу в списке bases и используйте эти значения для создания полей формы. Таким образом, product_name будет Label, а id - id поля. Позже я буду использовать Jquery для этих полей, чтобы получить значения.

У меня есть следующий код:

from django import forms
from django.db import models
from django.core.exceptions import ValidationError

from .models import Department, Test_list, Products, Current_tests

class Batch(forms.Form):
    bases = Products.objects.all().values_list('product_name','id')
    
    for i in bases: 
        for j in [0,1]:
            bn = i[0]
            bnid = i[1]
            name = forms.IntegerField(label=f"{bn}",widget=forms.NumberInput(attrs={"id":bnid}))

Код действительно работает, но вместо того, чтобы получить количество текстовых вводов, равное количеству строк в моей базе данных, он показывает только последнюю строку. Я полагаю, что это происходит потому, что в цикле я просто переназначаю другое значение "name". Сам цикл работает, и если я выведу i[0], он выведет все записи в столбце. Это связано с тем, как я добавляю поле в форму.

Любая помощь в решении этой небольшой проблемы будет очень признательна.

Вы можете сделать это в методе __init__ вашей формы.

class Batch(forms.Form):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        bases = Products.objects.all().values_list('product_name', 'id')
        
        for product_name, product_id in bases:
            self.fields[str(product_id)] = forms.IntegerField(
                label=product_name,
                widget=forms.NumberInput(attrs={"id": product_id})
            )

Это создаст поле для каждого товара в базе данных. Каждое поле добавляется в форму на основе цикла, поэтому вы можете создать столько полей ввода, сколько строк в вашей базе данных.

Есть два способа. Наиболее правильным, на мой взгляд, будет работать с formsets, таким образом, вы сможете легко изменять и сохранять несколько объектов:

views.py

def batch(request):
    qs = Products.objects.all()

    ProductsFormSet = formset_factory(Batch, extra=0)
    initial = [{"id": obj.id, "product_name": obj.product_name} for obj in qs]
    formset = ProductsFormSet(initial=initial)

    return render(request, "batch.html", {"formset": formset})

forms.py

class Batch(forms.Form):
    name = forms.IntegerField()

    def __init__(self, *args, **kwargs):
        super(Batch, self).__init__(*args, **kwargs)
        self.fields["name"].label = self.initial["product_name"]
        self.fields["name"].initial = self.initial["id"]

Второй вариант

Для динамического создания полей в одной форме, как вы хотите:

views.py

def batch(request):
    qs = Products.objects.all()
    form = AlternativeBatch(queryset=qs)

    return render(request, "batch.html", {"form": form})

forms.py

class Batch(forms.Form):
    def __init__(self, queryset, *args, **kwargs):
        super(Batch, self).__init__(*args, **kwargs)
        for product in queryset:
            self.fields[str(product.id)] = forms.IntegerField(
                label=product.product_name, initial=product.id
            )
Вернуться на верх