【问题标题】:Django: form to query databaseDjango:查询数据库的表单
【发布时间】:2015-04-27 10:10:06
【问题描述】:

我希望用户能够执行以下查询:

在两个日期内获取所有有全职合同的人,没有博士学位。

在 Django 中翻译:

Contract.objects.filter(
    person__is_doctor = False,
    type_contract = 'full',
    starting_date__gte = start_date,
    ending_date__lte = end_date
    )

如何制作表单/视图/模板以允许用户同时输入 start_dateend_date 并显示结果?

模型

class Person(models.Model):
        name    = models.CharField(max_length=32)
        surname = models.CharField(max_length=32)
        address = models.CharField(max_length=32)
        is_doctor  = models.NullBooleanField(blank=True, verbose_name=_(u"Phd?")

TYPE_CONTRACT = (
    ('PT', 'Partial time'),
    ('FC', 'Full contract')
    )           

class Contract(models.Model):
        person        = models.ForeignKey(Person) #person hired
        type_contract = models.CharField(max_length = 9, blank = True, choices = TYPE_CONTRACT)
        starting_date = models.DateField(blank = True, null = True)
        ending_date   = models.DateField(blank = True, null = True)

【问题讨论】:

    标签: django django-forms django-templates django-views django-queryset


    【解决方案1】:

    这是主要思想,另外你必须检查 start_date 和 end_date 是否真的在 clean_data 中,并在使用 filter() 时考虑到这一点。

    表格

    class MyForm(forms.Form):
        start_date = forms.DateField(initial=datetime.date.today)
        end_date = forms.DateField(initial=datetime.date.today)
    

    查看

    def my_view(request):
        contracts = Contract.objects.filter(person__is_doctor=False, type_contract='full')
        # if this is a POST request take start_date and end_date into account
        if request.method == 'POST':
            form = MyForm(request.POST)
            if form.is_valid():
                contracts = contracts.filter(starting_date__gte=form.cleaned_data.get('start_date'), ending_date__lte=form.cleaned_data.get('end_date'))
        else:
            form = MyForm()
        # do everything else that you need to do before returning a response
        return render_to_response('template.html', locals(), context_instance=RequestContext(request))
    

    模板

    <form action="" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit" />
    </form>
    
    {% for contract in contracts %}
        {{ contract.person }}
    {% endfor %}
    

    【讨论】:

    • 这没有回答问题:告诉我所有的人,没有博士学位,有两个日期之间的全职合同。,以及@987654324 的情况@ 称呼?还在使用 Django 1.2?
    • 我是这么想的:我如何制作表单/视图/模板以允许用户同时输入 start_date 和 end_date 并显示结果? 是实际问题。代码来自 Django 1.7
    • 这允许用户填写表格,但结果在哪里?不要粗鲁,但您的视图代码已经过时了。
    • 我已经更新了我的答案。你能指出我认为什么是过时的吗?谢谢
    • 以我的回答为例。不需要额外的 if 语句来实例化带有 post 数据的表单,而且我们很长一段时间都不必手动构造 RequestContext。如果您将几个变量传递给模板,则使用locals() 是可以的,但要小心使用带有大量变量的变量。
    【解决方案2】:

    首先,我将重构Contract 模型以更好地封装选择,另外,为什么合同允许开始日期和结束日期为空值?从业务逻辑的角度来看,这对我来说似乎很奇怪。

    class Contract(models.Model):
        PT = 'Part Time'
        FC = 'Full Contract'
        CONTRACT_CHOICES = (
            ('PT', PT),
            ('FC', FC)
        )
        person        = models.ForeignKey(Person)
        type_contract = models.CharField(max_length=9, choices=CONTRACT_CHOICES,
            default=PT)
        starting_date = models.DateField()
        ending_date   = models.DateField()
    
    # view
    
    from django.shortcuts import render
    from .forms import ContactForm
    
    def filter_contracts(request):
        form = ContractForm(request.POST or None)
        contracts = None
    
        if request.method == 'POST':
            if form.is_valid():
                # encapsulating the contract values means you don't have to
                # hand-code them in the query so your code stays DRY
                contracts = Contract.objects.filter(person__is_doctor=False,
                    type_contract=Contract.FC,
                    starting_date__gte=form.cleaned_data.get('starting_date'),
                    ending_date__lte=form.cleaned_data.get('ending_date'))
                # you might want to specify an order_by here
        return render(request, 'your_template.html', {'form': form,
            'contracts': contracts})
    
    # template
    
    <form action="." enctype="application/x-www-form-urlencoded" method="post">
        <ol>
            {{ form.as_ul }}
        </ol>
        {% csrf_token %}
        <button type="submit">Search</button>
    
        {% if contracts %}
        <table>
            {% for contract in contracts %}
            <tr>
                <td>{{ contract.person }}</td>
                <td>{{ contract.type_contract }}</td>
                <td>{{ contract.starting_date }}</td>
                <td>{{ contract.ending_date }}</td>
            </tr>
            {% endfor %}
        </table>
        {% endif %}
    </form>
    

    【讨论】:

    • 好的,我已经删除了我的答案,因为语义相同但质量不同。
    • 无需删除您的答案。人们看到他们之间的差异是件好事。
    • @Brandon 首先,谢谢。我在编辑 url.py 时遇到问题。 NameError at /admin/db_personal/query/ global name 'ContractForm' is not defined Request Method: GET Request URL: http://localhost:8000/admin/db_personal/query/ Django Version: 1.7c1 Exception Type: NameError Exception Value: global name 'ContractForm' is not defined
    • 只需要在视图中导入表单类即可。我已经更新了答案。
    • @Brandon 但是,我需要创建一个表单吗?
    猜你喜欢
    • 2012-12-22
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 2010-12-21
    • 2019-03-30
    相关资源
    最近更新 更多