【发布时间】:2021-09-23 17:27:40
【问题描述】:
我有两个具有外键关系的模型
models.py
from django.db import models
# Create your models here.
class Project(models.Model):
STATUSES = (
('Ongoing', 'Ongoing'),
('Completed', 'Completed')
)
YEARS = (
(2019, 2019),
(2020, 2020),
(2021, 2021),
(2022, 2022)
)
name = models.CharField(max_length=200)
client = models.CharField(max_length=100)
year = models.SmallIntegerField(choices=YEARS)
status = models.CharField(max_length=10, choices=STATUSES)
picture = models.ImageField(blank=True, null=True)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
class Photo(models.Model):
project = models.ForeignKey("Project", on_delete=models.CASCADE, related_name="images", blank=True, null=True)
image = models.ImageField()
description = models.CharField(max_length=100, blank=True, null=True)
slide = models.BooleanField(default=False)
我希望在同一个表单上创建照片和项目,所以我使用了 inline_formset_factory
forms.py
from django.forms import inlineformset_factory
from projects.models import Photo, Project
from django.forms import ModelForm
class ProjectModelForm(ModelForm):
class Meta:
model = Project
fields = (
'name',
'client',
'year',
'picture',
'status',
'description',
)
class PhotoModelForm(ModelForm):
class Meta:
model = Photo
fields = (
'image',
'slide',
'description'
)
PhotoFormset = inlineformset_factory(Project, Photo, form=PhotoModelForm, extra=1)
我使用了通用的 CreateView
views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from projects.forms import PhotoFormset, ProjectModelForm
from django.shortcuts import redirect, reverse, render
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from .models import Photo, Project
# Create your views here.
class ProjectCreateView(LoginRequiredMixin, CreateView):
template_name = 'projects/project_create.html'
form_class = ProjectModelForm
def get_context_data(self, **kwargs):
context = super(ProjectCreateView, self).get_context_data(**kwargs)
context['photos_formset'] = PhotoFormset()
return context
def post(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
photo_formset = PhotoFormset(self.request.POST)
if form.is_valid() and photo_formset.is_valid():
return self.form_valid(form, photo_formset)
else:
return self.form_invalid(form, photo_formset)
def form_valid(self, form, photo_formset):
self.object = form.save(commit=False)
self.object.save()
print('valid')
photos = photo_formset.save(commit=False)
for photo in photos:
photo.project = self.object
photo.save()
return reverse('projects:projectspage')
def form_invalid(self, form, photo_formset):
if not photo_formset.is_valid():
print('invalid formset')
return self.render_to_response(
self.get_context_data(form=form, photos_formset=photo_formset)
)
def get_success_url(self):
return reverse('projects:projectspage')
这是模板
{% extends 'base.html' %}
{% load crispy_forms_filters %}
<!-- crispy_forms_tags -->
{% block content %}
<div class="container">
<h2>create new project</h2>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<h2 class="display-6 my-5">
Add photos
</h2>
{{ photos_formset.as_p }}
<input type="submit" value="Create" class="btn btn-primary">
</form>
</div>
{% endblock content %}
当我提交form_invalid时从视图的post方法返回
我如何让 inline_formset 验证或有更好的方法来做它
【问题讨论】:
标签: python django django-views django-forms inline-formset