ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Django如何实现多对一数据的添加

2022-01-12 13:34:52  阅读:139  来源: 互联网

标签:name form models self Django forms 添加 数据 formset


例如:新增一个文章时,需要"新增另一个"的按钮
关键词:django、inlineform、form

目标效果:

image

参考链接:

具体实现

  • 安装两个第三方的包:

    pip install django-crispy-forms django-dynamic-formsets
    
  • models.py

    class Articles(models.Model):
        user = models.ForeignKey(Client,on_delete=models.CASCADE,verbose_name="所属用户")
        content = models.CharField(max_length=200,verbose_name="正文")
        create_time = models.DateTimeField(auto_now_add=True,verbose_name="创建时间")
        last_edit_time = models.DateTimeField(auto_now=True,verbose_name="最后一次编辑时间")
        is_public = models.CharField(max_length=5,choices=(("T","发布"),("F","仅自己可见")),verbose_name="是否发布")
        view = models.PositiveSmallIntegerField(default=0,verbose_name="阅读数")
        like = models.PositiveSmallIntegerField(default=0,verbose_name="点赞数")
    
        class Meta:
            verbose_name = "文章"
            verbose_name_plural = verbose_name
            ordering = ["-create_time"]
    
    
    
    class Images(models.Model):
        img = models.FileField(upload_to="articles_img",verbose_name="图片")
        articles = models.ForeignKey(Articles,on_delete=models.CASCADE,verbose_name="所属文章")
        create_time = models.DateTimeField(auto_now_add=True,verbose_name="上传时间")
    
        class Meta:
            verbose_name = "文章图片"
            verbose_name_plural = verbose_name
            ordering = ["-create_time"]
    
  • urls.py

    from django.urls import path
    from main_app import views
    
    app_name = 'main_app'
    
    urlpatterns = [
        path('create_articles/',views.ArticlesCreate.as_view(),name="create_articles"),
        ...
    ]
    
  • views.py

    from main_app import models
    from main_app import forms
    
    class ArticlesCreate(LoginRequiredMixin,CreateView):
        model = models.Articles
        template_name = "articles_add.html"
        form_class = forms.ArticlesForm
        success_url = None
    
        def get_context_data(self, **kwargs):
            data = super(ArticlesCreate, self).get_context_data(**kwargs)
            if self.request.POST:
                data['images_formset'] = accounts_forms.ImagesFormSet(self.request.POST,self.request.FILES)
            else:
                data['images_formset'] = accounts_forms.ImagesFormSet()
            return data
    
        def form_valid(self, form):
            context = self.get_context_data()
            images_formset = context['images_formset']
            with transaction.atomic():
                form.instance.user = self.request.user.client
                self.object = form.save()
                if images_formset.is_valid():
                    images_formset.instance = self.object
                    images_formset.save()
            return super(ArticlesCreate, self).form_valid(form)
    
        def get_success_url(self):
            return reverse_lazy('main_app:index')
    
    
  • forms.py

    from django import forms
    from django.forms.models import inlineformset_factory
    
    from crispy_forms.helper import FormHelper
    from crispy_forms.layout import Layout, Field, Fieldset, Div, HTML, ButtonHolder, Submit
    
    from main_app import models
    from main_app.custom_layout_object import Formset
    
    class ImagesForms(forms.ModelForm):
        class Meta:
            model = models.Images
            fields = ("img",)
    
    ImagesFormSet = inlineformset_factory(
        models.Articles,
        models.Images,
        form=ImagesForms,
        extra=1,
        can_delete=True
    )
    
    class ArticlesForm(forms.ModelForm):
        content = CustomCharField(label="正文",widget=forms.Textarea(attrs={"rows":3}))
        class Meta:
            model = models.Articles
            fields = ("content","is_public")
    
        def __init__(self, *args, **kwargs):
            super(ArticlesForm, self).__init__(*args, **kwargs)
            self.helper = FormHelper()
            self.helper.form_tag = True
            self.helper.form_class = ''
            self.helper.layout = Layout(
                Div(
                    Field('content'),
                    Field('is_public'),
                    Fieldset('添加图片',
                             Formset('titles')),
                    ButtonHolder(Submit('submit', '保存')),
                )
            )
    
    
  • main_app/custom_layout_object.py

    from crispy_forms.layout import LayoutObject, TEMPLATE_PACK
    from django.shortcuts import render
    from django.template.loader import render_to_string
    
    
    class Formset(LayoutObject):
        template = "formset.html"
    
        def __init__(self, formset_name_in_context, template=None):
            self.formset_name_in_context = formset_name_in_context
            self.fields = []
            if template:
                self.template = template
    
    
        def render(self, form, form_style, context, template_pack=TEMPLATE_PACK):
            formset = context[self.formset_name_in_context]
            return render_to_string(self.template, {'formset': formset})
    
  • formset.html

    这里我新增了一些js代码用于隐藏不需要的按钮

    {% load crispy_forms_tags %}
    {% load static %}
    {% load crispy_forms_tags %}
    <table class="col-md-9" style="margin-left: 10px;">
    {{ formset.management_form|crispy }}
        {% for form in formset.forms %}
            <tr class="{% cycle 'row1' 'row2' %} formset_row-{{ formset.prefix }}">
                {% for field in form.visible_fields %}
                <td>
                    {# Include the hidden fields in the form #}
                    {% if forloop.first %}
                        {% for hidden in form.hidden_fields %}
                            {{ hidden }}
                        {% endfor %}
                    {% endif %}
                    {{ field.errors.as_ul }}
                    {{ field|as_crispy_field }}
                </td>
                {% endfor %}
            </tr>
        {% endfor %}
    
    </table>
    <br>
    <script src="{% static 'bootstrap/jquery-3.6.0.min.js' %}"></script>
    <script src='{% static "dynamic_formsets/jquery.formset.js" %}'></script>
    <script type="text/javascript">
        $('.formset_row-{{ formset.prefix }}').formset({
            addText: '<i class="bi bi-plus"></i>新增另一个',
            deleteText: '<i class="bi bi-trash"></i>删除',
            prefix: '{{ formset.prefix }}',
        });
        $("input[type='checkbox']").each(hiddenLabel)
        function hiddenLabel(index,element){
            console.log(element)
            $(element).attr("hidden",true)
            $($(element)[0].labels[0]).attr("hidden",true)
        }
    
    </script>
    
  • articles_add.html

    {% extends "base.html" %}
    {% load crispy_forms_tags %}
    {% block title %}编辑文章{% endblock %}
    {% block css %}
        <style>
            .asteriskField{
                color: red;
            }
            .col-md-9 label{
                color: grey !important;
            }
            .delete-row{
                color: red !important;
                font-size: 1rem !important;
            }
        </style>
    {% endblock %}
    {% block content %}
    <div class="container">
        <div class="card">
            <div class="card-header">
                编辑文章
            </div>
            <div class="card-body">
                 {% crispy form %}
            </div>
        </div>
    </div>
    {% endblock content %}
    {% block js %}
        <script>
            $("form").attr("enctype","multipart/form-data")
        </script>
    {% endblock %}
    

标签:name,form,models,self,Django,forms,添加,数据,formset
来源: https://www.cnblogs.com/lisicn/p/15792227.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有