用于查询数据库的 Django 表单。是否需要form.py以及如何留空查询?

Django form for querying database. Is form.py needed and how to leave fields empty for query?

我想要一个输入表单,用户可以在其中输入 incident_idequipment_id 或两者。我现在遇到的问题是,例如,如果我填写 incident_id 并将 equipment_id 留空,即使 incident_id 找到匹配项,查询也将 return 没有命中,因为我的查询在搜索中使用空白 equipment_id。我如何设置它,以便当我将一个字段留空时,它不会在查询中使用它?我需要验证这些数据吗?我不会将其中的任何内容插入数据库。

我知道Django表单使用POST,但在这种情况下我觉得GET更合适,这意味着我不必使用Django表单,但这是否意味着我也没有验证数据?还是我应该只使用 POST 并使用 Django 表单验证该数据?对不起,这太概念化了。我在网上找不到很多好的答案。

model.py

from django.db import models

class Incident(models.Model):
incident_id = models.CharField(max_length=1000, blank=True)
equipment_id = models.ForeignKey(Equipment, blank=True)

class Equipment(models.Model):
        equipment_id = models.CharField(primary_key=True, max_length=100)
        manufacturer = models.ForeignKey(Manufacturer)
        equipment_category = models.ForeignKey(Equipment_Category)
        validated= models.BooleanField(default=True)
        in_service_date = models.DateTimeField('in service date', default=timezone.now)

view.py

@login_required
def search_incidents_query(request):

            if request.method == 'GET':

                            incident_id_query = request.GET.get('incident_id')
                            equipment_id_query = request.GET.get('equipment_id')

                            try:
                                            incident_id = str(incident_id_query)
                            except ValueError:
                                            incident_id = None
                            try:
                                            equipment_id = str(equipment_id_query)
                            except ValueError:
                                            username = None

                            list = [incident_id,equipment_id]

                            if all(x is None for x in list): #check if `list` contains only None
                                            incident_list = None #this in case the query comes back empty
                            else: #perform query

                                            incident_list = Incident.objects.filter(incident_id=incident_id, equipment_id=equipment_id)
                                                                                                                            )                              
                            return render(request, 'search_incidents_query.html', { 
                                            'incident_list' : incident_list
                            })

search_incidents_query.html

{% extends "base.html" %}
{% load widget_tweaks %}

{% block content %}
<br>

<div class="container-fluid">

    <!-----INPUT FORM------------------->
    <form method='GET' action='/search_incidents/'>
        <div class="row">   
            <div class="form-group col-md-3">
                <label>Incident ID</label>
                <input type="text" name="incident_id" value="{{ incident_id_query }}" class="form-control"/>
            </div>              
            <div class="form-group col-md-3">               
                <label>Equipment ID</label>
                <input type="text" name="equipment" value="{{ equipment_id_query }}" class="form-control"/>
            </div>
        </div>
    </form>
</div>
{% endblock %}

查询

对于类似的查询,您应该使用 Q 对象。

from django.db.models import Q 

Incident.objects.filter(
     Q(incident_id=incident_id) | Q(equipment_id=equipment_id)
)

更多关于 Q objects

此外,IMO 此代码需要以某种形式存在 class。如果是我,我会把这段代码放在一些

形式

class IncidentSearchForm(forms.Form):
    incident = forms.CharField(required=False)
    # ModelChoiceField because we want django to do the validation for us
    # TextInput because the default widget is a select tag
    equipment = forms.ModelChoiceField(Equipment.objects.all(), required=False, widget=forms.TextInput)  # TextInput because

    def clean(self):
         # I'd use the clean method to force the user to provide either an incident or equipment value

    def search(self):
        return Incident.objects.filter(
              Q(incident_id=self.cleaned_data['incident']) | 
              Q(equipment_id=self.cleaned_data['equipment'])
        )

景色

  • 您为什么不使用 Class 基于视图?
  • username = None。哇?

应该使用表格,因为never trust user input

@login_required
def search_incidents_query(request):
    form = IncidentSearchForm(request.GET or None)
    incident_list = None     
    if 'equipment' in request.GET or 'incident' in request.GET:
         incident_list = None  # Or maybe Incident.objects.none()  
         if form.is_valid():
            incident_list = form.search()

    return render(request, 'search_incidents_query.html', {'form' : form})

模板

<form method='GET' action='/search_incidents/'>
    <div class="row">   
        <div class="form-group col-md-3">
            {{ form.incident }}
        </div>              
        <div class="form-group col-md-3">               
            {{ form.equipment }}
        </div>
    </div>
    <input type="submit" />
</form>

您可以使用表单上的小部件将 form-control class 添加到字段中。