Другой способ управления экземпляром Django Model из ModelChoiceField в форме - PullRequest
0 голосов
/ 26 мая 2018

Я не уверен, если это возможно.Я пытаюсь использовать Django (2.0) Form и Formset в представлении.Вот мои модели:

from uuid import uuid4

class Aliment(models.Model):
    id = models.CharField(max_length=36, primary_key=True, unique=True, default=uuid4, editable=False)
    libelle = models.CharField(max_length=50)
    def __str__(self):
        return self.libelle

class Menu(models.Model):
    id = models.CharField(max_length=36, primary_key=True, unique=True, default=uuid4, editable=False)
    libelle = models.CharField(max_length=50)
    aliments = models.ManyToManyField(Aliment, through='Ingredient')
    def __str__(self):
        return self.libelle

class Ingredient(models.Model):
    id = models.CharField(max_length=36, primary_key=True, unique=True, default=uuid4, editable=False)
    aliment = models.ForeignKey(Aliment, on_delete=models.CASCADE)
    menu = models.ForeignKey(Menu, on_delete=models.CASCADE)
    quantite = models.IntegerField(default=0)
    def __str__(self):
        return "({0}:{1})".format(self.quantite, self.aliment)

Я использую Formset для обработки ('aliment', 'quantite') из Ingredient.Вот мои формы:

class MenuModelForm(forms.ModelForm):
    class Meta:
        model = Menu
        fields = ['libelle',]

class IngredientModelForm(forms.ModelForm):
    class Meta:
        model = Ingredient
        fields = ['aliment', 'quantite',]

Основная цель состоит в том, чтобы Menu иметь несколько классов Aliment - Ingredient.С помощью javascript я динамически добавляю элемент Aliment из одного списка (list1) в список Menu.Ingredient (list2).

Единственный способ для пользователя добавить элемент в список 2 - нажать некоторую «кнопку добавления» в списке 1.

Проблема в том, что ModelChoiceField поставляется с select, который содержит все Aliment экземпляриз базы данных.

Я хотел бы управлять своего рода кортежем ('aliment.id', 'aliment.libelle', 'quantite') для каждого Ingredient, который принадлежит Menu экземпляру.

С одной стороны, я мог бы отображатьв моем шаблоне Ingredient formset, что-то вроде этого:

<table>
    {% for item in menu.ingredient %}
        <tr>
            <td>
                <p name="{{ item.aliment.html_name }}" id="{{ fs.aliment.id_for_label }}"
                value="{{ item.aliment.id }}">{{ fs.aliment.libelle }}</p>
            </td>
            <td><input type="number" name="{{ item.quantite.html_name }}" value="{{ item.quantite.value }}" id="{{ item.quantite.id_for_label }}" /></td>
        </tr>
    {% endfor %}
</table>

С другой стороны, как получить Aliment экземпляр Ingredient formset итерации?

Я неНе знаю, были ли для этого созданы философия Django Form и Django.

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

Спасибо!

1 Ответ

0 голосов
/ 28 мая 2018

Я понял, что смутился, задавая вопрос.В следующий раз я постараюсь быть более кратким.

В любом случае, я нашел решение многих проблем (может быть, вы поймете, что я имел в виду: p).

Я добавил поле libelle вmy IngredientModelForm вот так:

class IngredientModelForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print(kwargs['instance'])
        self.fields['libelle'].initial = kwargs['instance'].aliment.libelle

    class Meta:
        model = Ingredient
        fields = ['aliment', 'quantite',]

    libelle = forms.CharField(max_length=50)

Так что я могу получить доступ к полю libelle в моем шаблоне.
В моем файле просмотра я сделал это так:

def add_menu(request):
    ingredientFormSet = modelformset_factory(Ingredient, form=IngredientModelForm, fields=('aliment', 'quantite'), extra=0)
    if request.method == 'POST':
        form = MenuForm(request.POST)
        formset = ingredientFormSet(request.POST)
        if form.is_valid() and formset.is_valid():
            ...
    else:
        menu = Menu.objects.all()[0]
        form = MenuModelForm(instance=menu)
        formset = ingredientFormSet(queryset=menu.ingredient_set.all())

Таким образом, для каждого экземпляра IngredientModelForm его начальное значение для поля libelle будет значением Aliment экземпляра, прикрепленного к Ingredient.

Давайте рассмотрим шаблон:

<form action="" method="POST">
    {{ formset.management_form }}
    <ul>
        {% for fs in formset.forms %}
        <li>
        {{ fs.id.label_from_instance }}
            <span><input type="hidden" name="{{ fs.id.html_name }}" value="{{ fs.id.value }}" id="{{ fs.id.id_for_label }}" /></span>
            <span><input type="hidden" name="{{ fs.aliment.html_name }}" value="{{ fs.aliment.value }}" id="{{ fs.aliment.id_for_label }}" /></span>
            <span>{{ fs.libelle.value }}<input type="hidden" name="{{ fs.libelle.html_name }}" value="{{ fs.libelle.value }}" id="{{ fs.libelle.id_for_label }}" /></span>
            <span><input type="number" name="{{ fs.quantite.html_name }}" value="{{ fs.quantite.value }}" id="{{ fs.quantite.id_for_label }}" /></span>
        </li>
        {% endfor %}
    </ul>
    <input type="submit" value="Ajouter" />
</form>

Итак, я могу отобразить имя Aliment с помощью select widget (потому что мой выбор Aliment управляется с помощью другого списка).

Я не знаю, хорошая ли это практикадля Джанго.

Не стесняйтесь предложить другое простое решение!:)

...