【问题标题】:How do I use django formset_factories?如何使用 django formset_factories?
【发布时间】:2021-03-12 10:01:22
【问题描述】:

我正在尝试开发一个基于 django 的项目/网站,该项目/网站会记录最后带走我们狗的人。我对 django 很陌生,所以请忍受缺乏该领域的知识。我目前设置了我的项目,以便我有基于用户/家庭成员、家庭的狗、帖子(何时和谁带狗的日志)和动作的模型,这是一个使用狗的子类和将模型作为外键发布,以查看狗在被带出时是否撒尿或拉便。我坚持的部分是试图弄清楚我如何创建帖子表单。由于我们有两只狗,我需要表单/帖子页面来为每个存在的狗模型显示一组复选框(用于撒尿和拉便动作)。虽然我可以成功显示一个动作集,但我遇到了尝试显示正确数量的动作集以及发布动作集和帖子本身的困难。我一直在尝试使用 formset_factory 函数,但我对如何让它正常运行感到困惑。任何人都可以帮忙吗?我已经被这个问题困扰了很长一段时间,任何支持都将不胜感激。

models.py:

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse

class Dog(models.Model):
    name = models.CharField(max_length = 20)

class Post(models.Model):
    walker = models.ForeignKey(User, on_delete = models.CASCADE)
    time_posted = models.DateTimeField(default = timezone.now)
    issues = models.TextField(max_length = 300)

class Action(models.Model):
    post = models.ForeignKey(Post, on_delete = models.CASCADE)
    dog = models.ForeignKey(Dog, on_delete = models.CASCADE)
    peed = models.BooleanField(default = False)
    pooped = models.BooleanField(default = False)

forms.py:

from django import forms
from django.forms import formset_factory
from dog_log_app.models import *

class Log_Form(forms.ModelForm):  
    class Meta:  
        model = Post
        fields = ("issues",)

class Action_Form(forms.Form):
    peed = forms.BooleanField(initial = False, required = False)
    pooped = forms.BooleanField(initial = False, required = False)

views.py:

from django.shortcuts import render
from django.forms import formset_factory, modelformset_factory
from .models import Post, Dog, Action
from dog_log_app.forms import *
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect

def home(request):
    context = {
        'posts': Post.objects.all().order_by('-time_posted'),
        'actions': Action.objects.all(),
        'dogs': Dog.objects.all()
    }
    return render(request, 'dog_log_app/home.html', context)

def post(request):
    form_post = Log_Form(request.POST or None)
    form_actions = modelformset_factory(Action, fields = ('peed', 'pooped'), extra = Dog.objects.count())

    if request.method == 'POST':
        form_post = Log_Form(request.POST)


        if form_post.is_valid() and form_actions.is_valid():
            post_save = form_post.save(commit = False)
            post_save.walker = request.user
            post_save.save()
            form_actions.save()

            return HttpResponseRedirect('..')
    
    context = {
        'post': form_post,
        'action': formset_factory(Action_Form, extra = Dog.objects.count()),
        'dogs': Dog.objects.all()
    }
    return render(request, 'dog_log_app/post_form.html', context)

post_form.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Post</title>
</head>
<body>
    <div>
        <form method="POST">
            {% csrf_token %}
            <fieldset>
                <legend>Create Post</legend>
                <h3>{{dogs.name}}</h3>
                <p>{{action.as_p}}</p>
                <p>{{post.as_p}}</p>
            </fieldset>
            <div>
                <button type="submit" value="Ok">Post</button>
            </div>
        </form>
    </div>
</body>
</html>

【问题讨论】:

    标签: python django django-models django-views django-forms


    【解决方案1】:

    你可以尝试使用ajax来添加你想要的数量,我通常做的是使用表格:

    from django.forms import ModelForm
    from django.forms.models import inlineformset_factory
    
    class PostForm(ModelForm):
        class Meta:
            model = Post
            fields = (
                'issues',
            )
    
    class ActionForm(ModelForm):
        class Meta:
            model = Action
            fields = (
                'peed', 'pooped'
            )
    
    ActionFormSet = inlineformset_factory(
        Post, Action, form=ActionForm,
        fields = ['peed', 'pooped'], extra=1, can_delete=True,
    )
    

    创建表单后,我们继续查看视图,为方便起见,视图将基于类:

    from django.db import transaction
    from django.views.generic import CreateView, UpdateView
    
    from .models import Post
    from .forms import PostForm, ActionFormSet
    
    class PostCreateView(CreateView):
        template_name = 'your template'
        form_class = PostForm
        success_url = reverse_lazy('your url')
    
        def get_context_data(self, **kwargs):
            data = super().get_context_data(**kwargs)
            if self.request.POST:
                data['formset'] = ActionFormSet(self.request.POST)
            else:
                data['formset'] = ActionFormSet()
    
            return data
    
        def form_valid(self, form):
            context = self.get_context_data()
            formset = context['formset']
    
            with transaction.atomic():
                self.object = form.save()
    
                if formset.is_valid():
                    formset.instance = self.object
                    formset.instance.walker = self.request.user
                    formset.save()
    
            return super().form_valid(form)
    
    
    class PostUpdateView(UpdateView):
        template_name = 'your template'
        form_class = PostForm
        model = Post
        success_url = reverse_lazy('your url')
    
        def get_context_data(self, **kwargs):
            data = super().get_context_data(**kwargs)
            if self.request.POST:
                data['formset'] = ActionFormSet(
                    self.request.POST, instance=self.object)
            else:
                data['formset'] = ActionFormSet(instance=self.object)
    
            return data
    
        def form_valid(self, form):
            context = self.get_context_data()
            formset = context['formset']
    
            with transaction.atomic():
                self.object = form.save()
    
                if formset.is_valid():
                    formset.instance = self.object
                    formset.save()
    
            return super().form_valid(form)
    

    要显示信息,您可以使用 jquery 库来保存动态信息: enter link description here 这样配置就容易多了

    一个示例模板是:

    {% extends "base.html" %}
    {% load static %}
    
    {% block content %}
        <div class="container">
            <div class="card">
                <div class="card-content">
                    <h2>Agregar Proyecto</h2>
                    <div class="col-md-4">
                        <form id="form-container" method="post">
                            {% csrf_token %}
                            {{ form }}
                            <h2>Actions</h2>
                            <table>
                                {{ formset.management_form }}
                                {% for form in formset %}
                                    {% if forloop.first %}
                                        <thead>
                                            <tr>
                                                {% for field in form.visible_fields %}
                                                    <th>{{ field.label|capfirst }}</th>
                                                {% endfor %}
                                            </tr>
                                        </thead>
                                    {% endif %}
                                    <tr id="projects_data">
                                        {% 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 }}
                                            </td>
                                        {% endfor %}
                                    </tr>
                                {% endfor %}
                            </table>
                            <button type="submit" class="btn btn-success">{{ message }}</button>
                            <a href="{{ request.META.HTTP_REFERER }}" class="btn btn-danger">Cancel</a>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    {% endblock %}
    
    {% block script %}
        <script type="text/javascript">
            $(function () {
                $('#projects_data').formset({
                    prefix: '{{ formset.prefix }}',
                    addText: 'create',
                    deleteText: 'remove',
                });
            })
        </script>
    {% endblock %}
    

    并以这种方式动态添加数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-24
      • 2017-11-27
      • 2016-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多