首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用django formset_factories?

如何使用django formset_factories?
EN

Stack Overflow用户
提问于 2020-11-30 21:14:16
回答 1查看 36关注 0票数 0

我正尝试在一个基于django的项目/网站上工作,这个项目/网站记录了谁最后把我们的狗弄出来的。我是django的新手,所以请容忍在该领域知识的缺乏。我目前已经建立了基于用户/家庭成员、家庭的狗、帖子(记录何时以及谁取出狗的日志)和actions的模型,actions是一个子类,它使用狗和帖子模型作为外键来查看狗被取出时是否小便和/或大便。我被卡住的部分是试图弄清楚我如何创建post表单。因为我们有两条狗,所以我需要表单/post页面为每个现有的狗模型显示一组复选框(用于小便和大便动作)。虽然我可以成功地显示一个操作集,但我遇到了尝试显示正确数量的操作集以及发布操作集和帖子本身的困难。我一直在尝试使用formset_factory函数,但我对如何让它正常工作感到困惑。有人能帮上忙吗?我已经在这个问题上纠结了很长一段时间,任何支持我的人都会非常感激。

models.py:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
<!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>
EN

回答 1

Stack Overflow用户

发布于 2020-11-30 22:23:28

您可以尝试使用ajax添加您想要的金额,我通常使用的是表单:

代码语言:javascript
运行
复制
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,
)

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

代码语言:javascript
运行
复制
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,这样配置起来就容易多了

示例模板为:

代码语言:javascript
运行
复制
{% 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 %}

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65074289

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档