django - 在一个帖子请求中提交多个表单(与一键不同,因为我需要一起处理这两个表单的数据!)

Posted

技术标签:

【中文标题】django - 在一个帖子请求中提交多个表单(与一键不同,因为我需要一起处理这两个表单的数据!)【英文标题】:django - submit multiple forms in one post request (different from one click cause I need to process the data of those two forms together!) 【发布时间】:2022-01-13 21:08:36 【问题描述】:

我有三个模型jobpositionwagekitfee,它们通过 OneToMany 关系相关。

class JobPosition(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.ForeignKey(Title, on_delete=models.CASCADE)
    ...    

class Wage(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    amount = models.FloatField(blank=True,null=True)
    type = models.CharField(choices=WAGETYPE, max_length=30)
    position = models.ForeignKey(JobPosition, related_name='wages', on_delete=models.CASCADE, blank=True, null=True)

class KitFee(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    kit_name = models.CharField(max_length=20, blank=True, null=True)
    amount = models.FloatField(blank=True, null=True)
    type = models.CharField(choices=WAGETYPE, max_length=30)
    position = models.ForeignKey(JobPosition, related_name='kit_fees', on_delete=models.CASCADE, blank=True, null=True)

我正在构建一个用户界面,用户可以在其中创建具有相关工资和 kit_fee 的职位(假设现在只有一份工资和一份工具包费用)。

我面临的问题是我不确定如何以正确的方式发出帖子请求。

我创建了这两个表单并使用模板视图将它们提供给 django 模板。

class JobPositionForm(forms.ModelForm):
        class Meta:
            model = JobPosition
            fields = ['title','city','dept_head','files','department_budget']
       ...

class WageForm(forms.ModelForm):
        class Meta:
            model = Wage
            exclude = ['id']

我的看法

class NewPosition(MyLoginRequiredMixin,TemplateView):
    template_name = 'action/crew/position.html'
    def get_context_data(self, **kwargs):
        self.project = get_object_or_404(JobProject, id=kwargs['project_id'])
        context = super().get_context_data(**kwargs)
        context['position_form'] = JobPositionForm(project=self.project, user=self.request.user)
        context['wage_form'] = WageForm()
        context['kit_fee_form'] = KitFeeForm()
        return context

    def post(self,request, **kwargs):
        print(request.POST)
        self.project = get_object_or_404(JobProject, id=kwargs['project_id'])
        position_form = JobPositionForm(request.POST, project=self.project, user=self.request.user)
        wage_form = WageForm(request.POST)
        kit_fee_form = KitFeeForm(request.POST)
        print(kit_fee_form.data['amount'])
        print(wage_form.data['amount'])

页面呈现流畅,但是我现在意识到我不知道如何在单个发布请求中同时提交这两个表单,也不知道如何在处理发布请求时初始化视图中的表单。

我想过使用formset,但我不知道如何将它与不同的表单一起使用。

我想我总是可以手动使用 javascript 来解析每个值并将其放入同一个 POST...但我希望使用一些不错的 django 功能可以解决它。特别是因为手动方法不能很好地扩展。

<form id="position_form">
    <div id="title_div" style="margin-top: 20px;">
        <label for="id_title" style="margin-bottom: 5px;" class="lead">Title</label><br/>
        position_form.title
    <div id="city_div" style="margin-top: 20px;" onfocus="$('#title_creation_div').hide();">
        <label for="id_city" style="margin-bottom: 5px;" class="lead">City</label><br/>
        position_form.city
    </div>
    <br>
    <div class="inner" style="display: inline-block;margin-right: 5px;margin-left: 5px; text-align: center">
            <label for="OtherComp">Department Budget</label><br/>
            position_form.department_budget
    </div>
    <div class="inner" style="display: inline-block;margin-right: 5px;margin-left: 5px; text-align: center">
        <label for="TeamInfo">Department Head</label><br/>
         position_form.dept_head 
    </div>
   </form>

<form id="wage_form">
 <div id="outer" style="width:100%; margin-top: 20px ">
        <div class="inner" style="display: inline-block;margin-right: 5px;margin-left: 5px">
            <label for=" wage_form.amount.id_for_label ">Rate</label><br/>
            wage_form.amount
        </div>
        
        <div class="inner" style="display: inline-block;margin-right: 5px;margin-left: 5px; text-align: center">
         <label for=" wage_form.type.id_for_label ">Rate Type</label><br/>
         wage_form.type
          </div>
    </div>

</form>

有什么想法吗?

编辑 我正在使用这个 javascript 将所有表单发送到同一个发布请求中,它似乎工作正常。但是,我注意到许多字段具有相同的 id,因此我无法正确启动表单。此外,如果我开始在屏幕上添加额外的工资/kitfee,该过程似乎无法扩展。

$("form").submit(function (e) 
        e.preventDefault();
        let data_array = $("form").map(function()
            return $(this).serializeArray();
        );
        data_array.push(csrfmiddlewaretoken: " csrf_token ")
        console.log(data_array)
        $.ajax(
            type: "POST",
            url: "% if source == 'edit' %% url 'action:edit_position' project.id position.id %% else %% url 'action:new_position' project.id %% endif %",
            data:data_array,
            success:function(html)

                
            );
    );

【问题讨论】:

【参考方案1】:

由于您使用的是模型表单,因此您可以直接将请求传递到表单实例以同时处理两个表单...请参见下面的简单注册场景,其中正在处理两个模型表单(User_form 和 User_profile_Form),

Views.py

def signup(request):
    registered = False

    if request.method == "POST":
        
        user_form = User_form(data=request.POST)
        user_profileform = user_profile_form(data=request.POST)

        if(user_form.is_valid() and user_profileform.is_valid()):
            user = user_form.save()
            user.set_password(user.password)
            user.save()

            profile = user_profileform.save(commit=False)
            profile.user = user

                    
            if 'profile_picture' in request.FILES:
                profile.profile_picture = request.FILES['profile_picture']
            
            profile.save()

            registered = True
        
        else:
            print(user_form.errors, user_profileform.errors)

UPDATE 1 添加模板部分

<!DOCTYPE html>
% extends "base.html" %
% load static %
% load bootstrap_tags %

% block title %

Signup

% endblock %

% block body %
    <div class="container">
        % if registered %
            <h1>Thankyou for REGISTERING with us</h1>
            <br>
        <a href="% url 'homepage:home' %"> click here to continue </a>
        % else %
            <a href="% url 'registration:signin' %"> <h4 style="text-align: center;" > Already have an account ? </h4></a>
            <h3>PLEASE fill the registration form below</h3>
            <form enctype="multipart/form-data" method="POST">
                <div class="container sign-form">
                    % csrf_token %
                    <h4>
                    <u>Account Information : </u>
                     user_form |as_bootstrap  
                    <br>
                    <hr>
                    <br>
                    <u><h4>Personal Information :</h4></u>
                     user_profileform |as_bootstrap  
                    </h4>
                    <input type="submit" class = "btn btn-primary" name="submit" value="Sign Up" style="margin: 0% 15%; width: 70%">
                </div>
            </form>
        % endif %

% endblock %

【讨论】:

对,我的问题实际上是如何在同一个 post 请求中传递这两种形式。 从模板方面?你想知道我是如何从模板发送上面的 user 和 user_profile 表单的吗? 是的,我现在实际上分享了一个编辑。 您可以使用 django 在同一个请求中发送两个表单...只需将两个表单都放在一个表单标签中...我会在上面更新它 你说的“把两个表单都放在一个表单标签里”是什么意思

以上是关于django - 在一个帖子请求中提交多个表单(与一键不同,因为我需要一起处理这两个表单的数据!)的主要内容,如果未能解决你的问题,请参考以下文章

如何在表单提交之前将多个图像异步添加到 django 表单

如何使用 Django 模板在 HTML 表单操作中向“current_url”/submit 提交 POST 请求?

Django 视图从应该发送 POST 的表单接收 GET 请求

在引导模式中提交 Django 表单

在 Django 中一次提交中执行多个 save() 的最佳方法

在Django中一次提交中执行多个save()的最佳方法