django - Django 自定义表单和 GenericView
问题描述
以下代码正在运行,但我想知道是否有更优雅的方法。我必须传递 specie_id,这样我才能将品种过滤到相应的品种。我可以将 specie_id 传递给视图,但我也有 Resident 模型(“specie”)中的信息。
get() 和 post() 都有几乎相同的代码,都传递了 specie_id。
风景
class ResidentUpdate(UpdateView):
model = Resident
template_name = "administration/resident_form.html"
form_class = ResidentCreateForm
def get(self, request, pk):
initial = self.model.objects.get(id=pk)
form = self.form_class(instance=initial, specie_id=initial.specie.id)
return render(request, self.template_name, {"form": form})
def post(self, request, pk):
initial = self.model.objects.get(id=pk)
form = self.form_class(request.POST, specie_id=initial.specie.id, instance=initial)
if form.is_valid():
form.save()
return redirect("resident_detail", pk)
return render(request, self.template_name, {"form", form})
表格
class ResidentCreateForm(ModelForm):
class Meta:
model = Resident
fields = [
"name",
"specie",
"breed",
"gender",
"gender_status",
"birth_date",
"organization",
"social_behaviors",
"notes",
]
widgets = {
"birth_date": DateInput(attrs={"class": "flatpickr"}),
"specie": HiddenInput(),
}
def __init__(self, *args, **kwargs):
self.specie_id = kwargs.pop("specie_id", None)
super(ResidentCreateForm, self).__init__(*args, **kwargs)
self.fields["specie"].initial = self.specie_id
self.fields["breed"].queryset = Breed.objects.for_specie(self.specie_id)
编辑 :
@Alasdair 的回答很好,我想我更完善了一点。我的表单也用于创建视图。所以我添加了一个检查,看看我是否在 kwargs 中有 specie_id(创建),或者我是否必须使用实例中的 specie_id(更新)
def __init__(self, *args, **kwargs):
self.specie_id = kwargs.pop("specie_id", None)
super(ResidentForm, self).__init__(*args, **kwargs)
if not self.specie_id:
self.specie_id = self.instance.specie.id
self.fields["specie"].initial = self.specie_id
self.fields["breed"].queryset = Breed.objects.for_specie(self.specie_id)
解决方案
看起来你可以做到self.fields["breed"].queryset = Breed.objects.for_specie(self.initial.specie_id)
,那么你不需要传递specie_id
给表单。
class ResidentCreateForm(ModelForm):
class Meta:
model = Resident
fields = [
"name",
"specie",
"breed",
"gender",
"gender_status",
"birth_date",
"organization",
"social_behaviors",
"notes",
]
widgets = {
"birth_date": DateInput(attrs={"class": "flatpickr"}),
}
def __init__(self, *args, **kwargs):
super(ResidentCreateForm, self).__init__(*args, **kwargs)
self.fields["breed"].queryset = Breed.objects.for_specie(self.instance.specie_id)
注意我已经删除了specie
上面的隐藏输入,我认为没有必要。
UpdateView
负责传递instance
给表单,因此您可以简化视图。
from django.urls import reverse
class ResidentUpdate(UpdateView):
model = Resident
template_name = "administration/resident_form.html"
form_class = ResidentCreateForm
def get_success_url(self):
"""Redirect to resident_detail view after a successful update"""
return reverse('resident_detail', args=[self.kwargs['pk']]
推荐阅读
- python - 为什么这个 Keras Conv2D 层与输入不兼容?
- python - 没有外键的基于 SQLAlchemy 值的关系
- amazon-web-services - 两个办公室和一个 AWS VPC 之间的 VPN
- python - 为什么 print() 函数没有回显到控制台?
- xml - andorid studio更新后布局xml的问题
- c# - 在谷歌中搜索图片
- java - Spring boot META-INF/build-info.properties 不在工件中
- ios - 使用 isNode(_:insideFrustumOf:) 与 nodesInsideFrustum(of:) 时的不同结果
- r - R中的意外符号
- selenium - 网络内部发生身份验证弹出窗口