Возможно ли иметь поля TextInput на модели, которая использует ForeignKeys - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь создать сайт, который позволяет пользователям создавать и хранить рецепты. У меня есть модель рецепта, и я использую специальную «сквозную таблицу», чтобы иметь многочисленные ингредиенты для каждого рецепта (каждый ингредиент имеет свой собственный атрибут, такой как количество и единица измерения).

class recipe(models.Model):
    recipe_name = models.CharField(max_length=200, unique=True)
    description = models.CharField(max_length=200, default='N/A')
    ingredients = models.ManyToManyField('ingredient', through='recipe_ingredient', related_name='recipes')

    def __str__(self):
        return self.recipe_name


class recipe_ingredient(models.Model):
    recipe = models.ForeignKey('recipe', related_name='recipe_ingredients', on_delete=models.CASCADE)
    ingredient = models.ForeignKey('ingredient', related_name='recipe_ingredients', on_delete=models.CASCADE)
    unit = models.ForeignKey('unit', related_name='recipe_ingredients', on_delete=models.CASCADE)
    quantity = models.IntegerField()

    def __str__(self):
        return f'{self.quantity} {self.unit} {self.ingredient}'


class unit(models.Model):
    measurement_desc = models.CharField(max_length=50, unique=True)

    def __str__(self):
        return self.measurement_desc


class ingredient(models.Model):
    ingredient_name = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.ingredient_name

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

class RecipeForm(ModelForm):

    class Meta:
        model = recipe
        fields = ['recipe_name', 'description']

    def __init__(self, *args, **kwargs):
        super(RecipeForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = True
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-md-3 create-label'
        self.helper.field_class = 'col-md-9'
        self.helper.layout = Layout(
            Div(
                Field('recipe_name'),
                Field('description'),
                Formset('ingredients'),
                HTML("<br>"),
                ButtonHolder(Submit('submit', 'save')),
                )
            )


class IngredientForm(ModelForm):

    class Meta:
        model = recipe_ingredient
        fields = ['quantity', 'unit', 'ingredient']

IngredientFormset = inlineformset_factory(recipe, recipe_ingredient, form=IngredientForm, extra=1, can_delete=True)

Это работает нормально, если я вручную ввожу ингредиенты в базу данных, но если я пытаюсь изменить входные данные для ингредиентов на TextInputs, чтобы разрешить пользователь для создания новых ингредиентов не будет сохранять (из-за того, что эти ингредиенты отсутствуют в базе данных. Это мой обзор:

class CreateRecipe(CreateView):

    model = recipe
    form_class = RecipeForm
    template_name = 'mealplanner/recipe_create.html'

    def get_context_data(self, **kwargs):
        data = super(CreateRecipe, self).get_context_data(**kwargs)
        if self.request.POST:
            data['ingredients'] = IngredientFormset(self.request.POST)
        else:
            data['ingredients'] = IngredientFormset()
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        ingredients = context['ingredients']
        with transaction.atomic():
            self.object = form.save()
            if ingredients.is_valid():
                ingredients.instance = self.object
                ingredients.save()
        return super(CreateRecipe, self).form_valid(form)

    def get_success_url(self):
        return reverse_lazy('recipe-detail', kwargs={'pk': self.object.pk})

Я ошибаюсь или есть способ получить django сохранить новые ингредиенты в базе данных, когда пользователь создает новые рецепты?

1 Ответ

0 голосов
/ 31 марта 2020

что вы можете сделать, это перебрать набор форм и убедиться, что рецепт существует, если нет, то создайте его:

def form_valid(self, forms):
    for form in forms:
       if not form.cleaned_data["ingredient"]: # ingredient does not exists
           # create it here
       ...
...