Django - 在一页上检索 2 个独立查询集的数据

Django - Retrieve Data for 2 Separate Querysets On One Page

我正在使用 Django、PyCharm 2018.3.7、Python 3.7 和 Postgres。

不幸的是,我不明白如何在一个屏幕页面(Django 形式)上显示两个单独的查询集的结果,这两个查询集需要通过动态筛选请求 (GET) 传递的相同 ID。有一个 table/model (ASSIGNMENTS) 与另一个 table/model (PRODUCTS) 具有一对多关系。传递的 ID 是 ASSIGNMENTS.ID,它是 ASSIGNMENTS 的 PK 和 PRODUCTS 的 FK。

我没有尝试加入这两个查询集。我需要用户首先查看 ASSIGNMENT 的信息,然后在下面我希望他们看到属于该 ASSIGNMENT 的所有产品。

我不需要update/create数据,所以不需要POST。只想检索,GET,存在的数据。

下面是 models.py、views.py 和模板的代码。它仅适用于 ASSIGNMENTS。

MODELS.PY

    class Assignments(models.Model):
        id = models.DecimalField(db_column='ID', primary_key=True, max_digits=9, decimal_places=0)    
        name = models.CharField(db_column='NAME', unique=True, max_length=40)

        def __str__(self):
            return self.name + ' ' + '(' + '#' + str(self.id) + ')'

        class Meta:
            ordering = 'name',
            db_table = 'ASSIGNMENTS'

    class Products(models.Model):
        id = models.DecimalField(db_column='ID', primary_key=True, max_digits=11, decimal_places=0)  
        assignment = models.ForeignKey(Assignments, models.DO_NOTHING, related_name='productsfor_assignment', db_column='ASSIGNMENT_ID', blank=True, null=True)
        name = models.CharField(db_column='NAME', max_length=80)

        def __str__(self):
            return self.name + ' ' + '(' + '#' + str(self.id) + ')'

        class Meta:
            ordering = 'name',
            db_table = 'PRODUCTS'

VIEWS.PY

    def search_form(request):
        return render(request, 'assignments/search_form.html')

    def search(request):
        if 'q' in request.GET and request.GET['q']:
            q = request.GET['q']
            assign = Assignments.objects.filter(id__icontains=q)
            return render(request, 'assignments/search_results.html',
                {'AssignmentsResults': assign, 'query': q})
        else:
        # if the query is empty, render the 'search_form html' template again.
        # display an error message in that template.  So, pass a template variable.
        # 'search_form html' will check for the 'error' variable
            return render(request, 'assignments/search_form.html', {'error': True})

模板'search_form.html'

    {% extends "base.html" %}

    {% block content %}
    <br><br>
    <h1> Assignment ID Search Form </h1>
    <br><br>
        {% if error %}
            <p style="color: red;">Please submit a search term.</p>
        {% endif %}
        <form action="/search/" method="get">
            <input type="text" name="q" placeholder="Enter ID here ...">
            <input type="submit" value="Search">
        </form>

    <p>
        Page last updated: {{ last_updated|date:'D d F Y' }}
    </p>
    {% endblock content %}

模板'search_results.html'

    {% extends "base.html" %}

    {% block content %}

    <br><br>
    <h1> Assignment ID Search Results</h1>

    <p>You searched for: <strong>{{ query }}</strong></p>

    {% if AssignmentsResults %}
        <ul>
            {% for assignments in AssignmentsResults %}
            <li>
                {{ assignments.id }}, {{ assignments.name }}
            </li>
            {% endfor %}
        </ul>
    {% else %}
        <p>No assignments matched your search criteria.</p>
    {% endif %}

    {% endblock content %}

这是我最终放在一起以包含产品的内容(如下面失败的 views.py 和模板所示)。但是,它不起作用。

这是 失败的 VIEWS.PY

    def search_form(request):
        return render(request, 'assignments/search_form.html')

    def search(request):
        if 'q' in request.GET and request.GET['q']:
            q = request.GET['q']
            assign = Assignments.objects.filter(id__icontains=q)
            prod = Products.objects.filter(assignment__icontains=q)
            return render(request, 'assignments/search_results.html',
                {'AssignmentsResults': assign, 'query': q})
            return render(request, 'assignments/search_results.html',
                          'ProductsResults': prod, 'query': q)
        else:
            # if the query is empty, render the 'search_form html' template again.
            # display an error message in that template.  So, pass a template variable.
            # 'search_form html' will check for the 'error' variable
            return render(request, 'assignments/search_form.html', {'error': True})

这是失败的模板代码'search_results.html

    {% extends "base.html" %}

    {% block content %}

    <br><br>
    <h1> Assignment ID Search Results</h1>

    <p>You searched for: <strong>{{ query }}</strong></p>

    {% if AssignmentsResults %}
        <ul>
            {% for assignments in AssignmentsResults %}
            <li>
                {{ assignments.id }}, {{ assignments.name }}
            </li>
            {% endfor %}
        </ul>

        <p> These are the Products attached to the Assignment.</p>
        {% if ProductsResults %}
        <ul>
            {% for products in ProductsResults %}
            <li>
                {{ products.assignment }}, {{ products.name }}
            </li>
            {% endfor %}
        </ul>
        {% else %}
            <p> No products for this assignment exist.</p>
        {% endif %}
    {% else %}
        <p>No assignments matched your search criteria.</p>
    {% endif %}

    {% endblock content %}

我按照 Nigel George 的 'Build a website with Django 2, updated for Django 2.2' 创建了这个项目。我看过几个 youtube 教学视频并阅读了关于 Whosebug 的问题。 (这只是一对。)

How to combine two or more querysets in a Django view?

Django: Add queryset to inlineformsets

Django nested QuerySets

InlineFormSet with queryset of different model

但是,none 他们已经能够帮助我解决在一个表单上呈现 2 个单独的查询集结果的问题。

我非常感谢您提供的任何建议和帮助。 谢谢

好的,让我们看看。如果您只想显示 search_results.html 中的信息,我建议您按如下方式稍微重构您的查询。 (我会尽可能多地清理奇怪的东西(例如有两个连续的 return 语句)来说明我的观点)

views.py:

from django.shortcuts import render, redirect
from django.urls import reverse


def search(request):
    q = request.GET.get('q', None)
    if q:
        assignments_qs = Assignments.objects.filter(id__icontains=q) \
            .prefetch_related('productsfor_assignment')
        context_data = {'assignments': assignments_qs}
        return render(request, 'assignments/search_results.html', context_data)
    else:
        return redirect(reverse('search_form', kwargs={'error': True}))


def search_form(request, error=False):
    return render(request, 'assignments/search_form.html', {'error': error})

search_results.html

{% if assignments %}
    <ul>
        {% for assignment in assignments %}
            <li>
                {{ assignment.id }}, {{ assignment.name }}
            </li>                 
            {% if assignment.productsfor_assignment.exists %}
                <p> These are the Products attached to the Assignment.</p>
                <ul>
                {% for product in assignment.productsfor_assignment.all %}
                    <li>
                        {{ product.assignment }}, {{ product.name }}
                    </li>
                {% endfor %}
                </ul>
            {% endif %}
        {% endfor %}
    </ul>
{% else %}
    <p>No assignments matched your search criteria.</p>
{% endif %}

考虑到你目前拥有的东西,我认为这是实现你想要的最好和最相似的方法。