Django外键无法正常保存

时间:2018-02-19 23:11:37

标签: django django-models django-forms django-views foreign-keys

我在同一个模型中有多个外键,出于某种原因,每当我在表单上按提交时,最后一个外键都会覆盖之前输入的外键。有人能看到最新情况吗?

models.py

class Meal(models.Model):
    """
    Three of these will be given to a study
    """
    date = models.DateField(null=True, blank=True)
    start_time = models.TimeField(null=True, blank=True)
    stop_time = models.TimeField(null=True, blank=True)
    description = models.CharField(max_length=256, null=True, blank=True)

    class Meta:
        verbose_name_plural = 'Meals For Studies'

    def __str__(self):
        return "Meal Information for CRF # " + str(self.general_info.case_report_form_number)


class MotionStudyInstance(models.Model):
    # ###############ADD MEAL INFORMATION#######################
    meal_one = models.ForeignKey(Meal, related_name='first_meal', on_delete=models.CASCADE, null=True, blank=True)
    meal_two = models.ForeignKey(Meal, related_name='second_meal', on_delete=models.CASCADE, null=True, blank=True)
    meal_three = models.ForeignKey(Meal, related_name='third_meal', on_delete=models.CASCADE, null=True, blank=True)

    class Meta:
        verbose_name_plural = 'Motion Studies Awaiting Validation'

    def __str__(self):
        return "CRF: #" + str(self.general_info.case_report_form_number)

forms.py

class MealForm(forms.ModelForm):
    class Meta:
        model = Meal

views.py

class MotionStudyInstanceFormView(LoginRequiredMixin, View):
        def post(self, request):
            if request.method == 'POST':
                    form = MotionStudyInstanceForm(request.POST, request.FILES)
                    meal_one_form = MealForm(request.POST)
                    meal_two_form = MealForm(request.POST)
                    meal_three_form = MealForm(request.POST)
                    if meal_one_form.is_valid() and meal_two_form.is_valid() and meal_three_form.is_valid():
                        meal_one = meal_one_form.save()
                        meal_two = meal_two_form.save()
                        meal_three = meal_three_form.save()
                        motion_study_instance_one = form.save(commit=False)
                        motion_study_instance_one.meal_one = meal_one
                        motion_study_instance_one.meal_two = meal_two
                        motion_study_instance_one.meal_three = meal_three
                        motion_study_instance_one.save()
                        return redirect('data:motion-studies')
            else:
                 form = MotionStudyInstanceForm()
        return render(request, self.template_name, {'form': form})

motionstudyinstance_form.html

{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<div class="container">
    <h1>Motion Study Form</h1>
    <form method="POST" enctype="multipart/form-data">
        {% bootstrap_form form %}
        <p>Meal One Information</p>
        {% bootstrap_form meal_one_form %}
        <p>Meal Two Information</p>
        {% bootstrap_form meal_two_form %}
        <p>Meal Three Information</p>
        {% bootstrap_form meal_three_form %}
        <input class="btn btn-default" type="submit" value="Submit">
    </form>
</div>

{%endblock%}}

就像我说的,当我保存表格时,前两个用餐条目被覆盖,看起来像第三个的副本。我究竟做错了什么?我是django的新手。

2 个答案:

答案 0 :(得分:0)

我想知道为什么在一个html表单中复制三次相同的表单。但是,request.POST将始终具有相同的值。 即:虽然您复制了表单,但Django生成的输入将具有相同的名称。

description = models.CharField(max_length=256, null=True, blank=True)

{{form.description}} 

将生成

<input type="text" name="description" id="id_description" maxlength="256">

即使复制{{form}}两次,名称仍然是每个表单的描述。

所以request.POST [&#34; description&#34;]包含收到的最后一个或第一个值。

您可以在模板中生成3个表单,其中不同的操作遵循短的get参数。

<form action="/your_url/?form=1" method="post">
    {% bootstrap_form form %} <!-- the first form -->
    <!-- enter code here, with the submit button -->
</form>

<form action="/your_url/?form=2" method="post">
    {% bootstrap_form form %}<!-- the second form -->
    <!-- enter code here, with the submit button-->
</form>

<form action="/your_url/?form=3" method="post">
    {% bootstrap_form form %}<!-- the third form -->
    <!-- enter code here, with the submit button-->
</form>

您还可以为每个表单使用隐藏输入,以便准确了解提交的表单

<form action="/your_url/" method="post">
    {% bootstrap_form form %}<!-- the second form -->
    <input type="hidden" name="form" value="3">
    <!-- enter code here, with the submit button-->
</form>

在您看来:

if request.method == 'POST':
    form = MotionStudyInstanceForm(request.POST, request.FILES)
    # If GET parameter
    w = request.GET.get("form","") # form 1 , 2 or 3
    # If Hidden Input
    # w = request.POST.get("form","")
    if w == "1":
        pass

答案 1 :(得分:0)

下面的代码并不是最好的方法,但如果我明白你想做什么,它就能解决问题。

HTML:此处需要更多验证

<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
    {% for i in 'aaa' %} <!-- A way to duplicate three times ,foorloop with make them different -->
    <input type="text" required name="description{{forloop.counter}}" id="id_description{{forloop.counter}}">
    <input type="date" required name="date{{forloop.counter}}" id="id_date{{forloop.counter}}">
    <input type="text" required name="start_time{{forloop.counter}}" id="id_start_time{{forloop.counter}}">
    <input type="text" required name="stop_time{{forloop.counter}}" id="id_stop_time{{forloop.counter}}">
    {% endfor %}
    <button type="submit">Submit</button>
</form>

视图:此处还需要更多验证

if request.method == 'POST':
    n = {"1":"one","2":"two","3":"three"}
    # Create The Instance of MotionStudyInstance
    motion_study = MotionStudyInstance.objects.create()
    for i in range(1,4):
        i = str(i) # in order to concatane with string
        date = request.POST.get("date"+i,"")
        start_time = request.POST.get("start_time"+i,"")
        stop_time = request.POST.get("stop_time"+i,"")
        description = request.POST.get("description"+i,"")

        # Test if everything is ok with each input fields

        m = Meal.objects.create(
            date = date ,
            start_time = start_time,
            stop_time = stop_time,
            description = description,
        )   
        eval("motion_study.meal_"+n[i]) = m

    # Finally save the instance
    motion_instance.save()