【问题标题】:django - iterate through model in create view & return inline formsetdjango - 在创建视图中迭代模型并返回内联表单集
【发布时间】:2021-04-08 09:35:12
【问题描述】:

我正在尝试创建一个表单集,允许用户在使用CreateView 创建新项目时为每个Priority 设置分数。 Priority 模型已经具有关联的数据(3 个值)foreach Priority 已创建我试图在 Project CreateView 中返回一个字符字段,用户可以在其中输入 score Priority.

目前我在Project CreateView 中显示了三个字符字段,但没有保存优先级。我已经做了一些测试,看起来ProjectPriority 从来没有让ProjectPriority 值只设置分数值。

我已经努力了好几天试图让它发挥作用。感谢所有帮助。

Views.py

class ProjectCreateview(LoginRequiredMixin, CreateView):
    model = Project
    form_class = ProjectCreationForm
    success_url = 'home/project/project_details.html'

    def get_context_data(self, **kwargs):
        ChildFormset = inlineformset_factory(
            Project, ProjectPriority, fields=('priority', 'score'), can_delete=False, extra=Priority.objects.count(),
        )
        data = super().get_context_data(**kwargs)
        if self.request.POST:
            data['priorities'] = ChildFormset(self.request.POST, instance=self.object)
        else:
            data['priorities'] = ChildFormset(instance=self.object)
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        priorities = context["priorities"]
        self.object = form.save()
        if priorities.is_valid():
            priorities.instance = self.object
            priorities.save()
        return super().form_valid(form)

Models.py

class Priority(models.Model):
     title = models.CharField(verbose_name="Title", max_length=250)

     def __str__(self):
         return self.title

class Project(models.Model):
    name = models.CharField(verbose_name="Project Title", max_length=100)
    details = models.TextField(verbose_name="Project Details/Description", blank=False)
    priority = models.ManyToManyField(
        Priority,
        through='ProjectPriority',
        related_name='priority'
    )
    creator = models.ForeignKey(User, on_delete=models.CASCADE)

class ProjectPriority(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    priority = models.ForeignKey(Priority, on_delete=models.CASCADE)
    score = models.CharField(max_length=1000, choices=priority_choices)

    class Meta:
        verbose_name = "Priority"
        verbose_name_plural = "Priorities"

    def __str__(self):
        return f"Priority: {self.priority.title}, Score: {self.score}, Project: {self.project.name}"

模板

{% block content %}
<div class="container-fluid" style="margin-top: 25px;">
<div class="row">
<div class="col-xl-8">
<form method="POST">
    {% csrf_token %}
    <fieldset class="form-group">
        <legend class="border-bottom mb-4">New Project</legend>
        {{ form|crispy }}
    </fieldset>

    <h2>Priority Criteria</h2>
    {{ priorities|crispy }}
    <div class="form-group">
        <button class="btn btn-outline-info" type="submit">Create 
Project</button>
    </div>
</form>
</div>
</div>
{% endblock content %}

【问题讨论】:

  • 您已经在内联表单集上设置了fields=('score',),您希望如何将外键priority 设置为表单?改用fields=('priority', 'score')...
  • @AbdulAzizBarkat 设置 fields=('priority', 'score') 无效。它消除了错误,但 Priority 仍未与 Project 一起保存。

标签: django


【解决方案1】:

在您的 form_valid 方法中,您的代码如下:

def form_valid(self, form):
    context = self.get_context_data()
    priorities = context["priorities"]
    self.object = form.save()
    if priorities.is_valid():
        priorities.instance = self.object
        priorities.save()
    return super().form_valid(form)

但是此时尝试设置实例(在调用 is_valid 之后)将不起作用,因为当您调用 priorities.is_valid() 时表单已经构建,它会遍历表单集的缓存属性 forms,这会导致要使用 instance 构建的表单,然后设置为空表单(因为您尚未提供它)。解决方案是在调用is_valid 之前设置实例。另请注意,super().form_valid(form) 也会保存对象,您应该在那里自己返回响应:

from django.http import HttpResponseRedirect


class ProjectCreateview(LoginRequiredMixin, CreateView):
    # Other attributes and get_context_data here
    
    def form_valid(self, form):
        context = self.get_context_data()
        priorities = context["priorities"]
        self.object = form.save()
        priorities.instance = self.object # Set the instance here
        if priorities.is_valid():
            priorities.save()
        return HttpResponseRedirect(self.get_success_url())

【讨论】:

  • 我试过了,但没有收到任何错误,但是当我尝试使用 {{ project.priority }} 时,它会返回 home.Priority.None。我认为它仍然没有正确保存? (其余项目数据返回正常)
  • @GaryHost priority 是模型ManyToManyField 上的Project,这意味着project.priority 将为您提供相关经理。尝试改写{% for priority in project.priority.all %}{{ priority }}{% endfor %},这将呈现所有相关的优先级。 注意:忘记了之前评论中的.all
  • 我在 django 上很糟糕,感谢您的帮助。我收到'ManyRelatedManager' object is not iterable
  • @GaryHost 那是我的错,我已经转发了该评论,请参阅那里的.all 部分。再次明确{% for priority in project.priority.all %}{{ priority }}{% endfor %}
猜你喜欢
  • 2020-09-18
  • 2019-04-23
  • 1970-01-01
  • 2011-05-28
  • 2010-11-09
  • 1970-01-01
  • 2010-09-30
  • 1970-01-01
  • 2017-01-17
相关资源
最近更新 更多