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

2024-10-02 00:42:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Django创建一个web应用程序。我有多个Django模型,彼此之间有关系。我的一个模型叫做Type,另一个叫做TestEquipmentType模型与TestEquipment有多对多关系

为了允许用户创建一个新的Type,我有一个html表单,并选择将与该Type关联的TestEquipment,我正在使用带有“chips”(javascript)的可搜索下拉列表,它加载所有TestEquipment,并允许您搜索和选择要添加的多个对象。当用户提交表单时,将添加所选的TestEquipment

除了用户输入文本并按下enter键之外,其他一切都非常有效,而不是从下拉列表中选择,而是在芯片中添加该文本。当表单提交时,它尝试添加一个不存在的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)

创建_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"))

Tags: nametestdivtruenewmodelsrequesttype
1条回答
网友
1楼 · 发布于 2024-10-02 00:42:37

因此,最重要的事情是在python中执行检查,因为您不应该像这样对数据库执行get请求,除非您知道它不会失败。正如您所看到的,当对象不存在时,它只会导致500个错误

所以工作1就是在你看来做到这一点

    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中的所有值以确保它们存在。这样,您就可以再次呈现带有附加错误的表单

我已经看过了芯片的演示/文档,它看起来并不能帮助防止无效输入,但您可以自己用javascript进行一些验证,以防止提交

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

相关问题 更多 >

    热门问题