在创建具有相关模型中不存在的多对多字段选择的 Django 模型对象时,如何防止表单提交?



我正在使用Django创建一个web应用程序。我有多个Django模型,它们之间存在关系。我的一个模型叫Type,另一个叫TestEquipment。CCD_ 3模型与CCD_。

为了允许用户创建新的Type,我有一个html表单并选择哪个TestEquipment将与我使用的Type相关联;芯片";(javascript(,它加载所有TestEquipment,并允许您搜索和选择要添加的多个对象。当用户提交表单时,会添加所选的TestEquipment

除了当用户输入文本并按下回车键时,一切都很好,而不是从下拉列表中选择,而是添加了一个带有该文本的芯片。当表单提交时,它会尝试添加一个不存在的TestEquipment

我想找到一种方法,要么不允许添加不存在的对象,要么抛出警报";必须从现有的测试设备中选择";;不知何故,我必须确保表单不会提交给我的构造函数,并在向字段添加文本的情况下创建新的Type

我试图找到一个答案,但绝对没有运气。非常感谢您的帮助!

Django模型代码:

class TestEquipment(models.Model):
name = models.CharField(max_length=64, unique=True)
notes = models.TextField(null=True, blank=True)
def __str__(self):
return f"{self.name}"

class Type(models.Model):
name = models.CharField(max_length=64, unique=True)
type_folder = models.URLField(null = True, blank = True)
type_test_equipment = models.ManyToManyField(TestEquipment, blank=True, related_name="type_test_equipment")
type_notes = models.TextField(null=True, blank=True) 
test_sheet = models.URLField(null=True, blank=True) 
type_test_guide = models.URLField(max_length=300, null=True, blank=True)
objects = TypeManager()
def __str__(self):
return f"{self.name}"

Views.py代码:

def create_type_view(request):
if not request.user.is_authenticated:
return render(request, "jobs/login.html", {"message": None})
test_equipments = TestEquipment.objects.all()
equipment_types = Type.objects.all()
#pass in existing types of equipment
context= {
"equipment_types": equipment_types,
"test_equipments": test_equipments
}
if request.user.is_authenticated:
return render(request, "jobs/create_type.html", context)

create_type.html代码(引入实体化样式和javascript(:

<div> 
<form id="type_form" class="col s12" action="{% url 'create_type' %}" method="post">
{% csrf_token %}
<div class="row">

<div class="col s12">
<h6 style="color:#808080">Select Type-Specific Test Equipment</h6>
<div class="row">
<div class="input-field col s12">
<div id="test_equipment-chips" class="chips chips-autocomplete">
</div>
<input id="test_equipment" name="test_equipment" style="visibility: hidden;" value="">
</div>
</div>
</div>
</div>
<div class="row">
<input id="submit-btn" type="submit" value="Confirm Add" onclick="onSubmit();" />
</div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script>

function onSubmit() {
var chipInstance = M.Chips.getInstance($("#test_equipment-chips"));
var value = Array.from(chipInstance.chipsData.map(x=>x.tag)).join(",");
$("#test_equipment").val(value);

}

$('#test_equipment-chips').chips({
autocompleteOptions: {
data: {
{% for test_equipment in test_equipments %}
'{{test_equipment}}': null,
{% endfor %}
},
limit: Infinity,
minLength: 0,
}
});
</script>

构造函数代码:

def create_type(request):
#extract type name from form
type_name = request.POST["type_name"]
#create new type object
new_type=Type.objects.create_type(type_name)
#fill in all properties that were submitted in the form
new_type.type_folder = request.POST["type_folder"]
new_type.test_sheet = request.POST["test_sheet"]
new_type.type_test_guide = request.POST["type_test_guide"]
new_type.type_notes = request.POST["type_notes"]

equipment_list=request.POST["test_equipment"].split(",")

for equipment_name in equipment_list:

equipment=TestEquipment.objects.get(name=equipment_name)
new_type.type_test_equipment.add(equipment.pk)
#save to database
new_type.save()
return HttpResponseRedirect(reverse("jobs"))

因此,最重要的是在python中执行检查,因为除非知道不会失败,否则不应该对数据库执行类似的get请求。正如您所看到的,当对象不存在时,它只会出现500个错误。

因此,在你看来,第一项工作就是这样做;

for equipment_name in equipment_list:
try:
equipment=TestEquipment.objects.get(name=equipment_name)
except TestEquipment.DoesNotExist:
# Log the error somehow if you like?
print(f"Equipment not found with the name {equipment_name}")
else:
# This only executes when the exception wasn't raised
new_type.type_test_equipment.add(equipment.pk)

使用上面的代码,它只会忽略无效的输入,这适合最小可行的选项。但是,如果您希望在输入无效的情况下提供错误,则应在将equipment_list中的所有值添加到关系之前,先运行这些值以确保它们存在。这样,您就可以再次呈现带有错误的表单。

我看过芯片的demo/docs,它看起来不能帮助防止无效输入,但你可以自己用javascript进行一些验证,以防止提交。

您还应该考虑使用django的表单,因为您的视图是直接访问post数据的。通过使用表单,您可以处理视图之外的验证逻辑&它们还有很多好处。如果你还没有找到表格,请阅读这一页;https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Forms

最新更新