如何在 Django 的一个 url 地址中调用多个视图?

How can I call multiple views in one url address in Django?

我试图在 index.html 上显示由 new_measurement 定义的表单,但我只设法让 IndexView() 工作。我尝试了 IndexView()new_measurement() 之间的各种组合,但根本没有用。我知道 IndexView() 不会传递与 new_measurement() 相关的任何内容,并且不会调用 new_measurement(),这是我问题的核心。如果对 Django 有更多经验的人能告诉我我能做什么或应该做什么,我将不胜感激。谢谢。

这是我的 views.py:

from django.shortcuts import render
from django.utils import timezone
from .models import Measurement
from .forms import MeasurementForm
from django.views import generic


class IndexView(generic.ListView):
    model = Measurement
    context_object_name = 'measurement_list'
    template_name = 'index.html'
    queryset = Measurement.objects.all()


def new_measurement(request):
    if request.method == "POST":
        form = MeasurementForm(request.POST)
        if form.is_valid():
            measurement = form.save(commit=False)
            measurement.measurement_date = timezone.now()
            measurement.save()
    else:
        form = MeasurementForm()

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

urls.py:

from django.urls import path
from . import views


urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
]

forms.py:

class MeasurementForm(forms.ModelForm):
    class Meta:
        model = Measurement
        fields = ('measurement_value', 'measurement_unit')

index.html:

{% extends "base.html" %}

{% block content %}
    <h1>Climate Measurement Tool</h1>

    <h2>Add a new measurement</h2>
    <form method="POST" class="post-form">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="save">Add</button>
    </form>

    <h2>Measurements</h2>
    {% if measurement_list %}
    <ul>
        {% for measurement in measurement_list %}
        <li>
            <p>{{ measurement }}</p>
        </li>
        {% endfor %}
    </ul>
    {% else %}
        <p>No measurements yet</p>
    {% endif %}    
{% endblock %}

你不能为一个 url 调用 2 个视图。基本上每个 url 都必须链接到一个视图,这是你无法真正改变的。

但是如果你想让你的代码更简洁,有多个功能,你可以在你的视图中调用它们,基本上你可以做一个视图并在 url 甚至更多时调用它超过一个 url 已被使用,在该视图中决定使用哪个函数

示例:

def god_view(request):
    if request.method == "POST"
        return post_func(request)
    return get_func(request)

这是一个非常简单的示例,但您可以做很多其他事情。

您不能在一个视图中映射多个视图 url 但您可以在一个视图中执行多项工作。 更新您的 views.py,因为您可以看到我在该视图中发送(查询列表和表单)

views.py

def new_measurement(request):
    if request.method == "POST":
        form = MeasurementForm(request.POST)
        if form.is_valid():
            measurement = form.save(commit=False)
            measurement.measurement_date = timezone.now()
            measurement.save()
    else:
        form = MeasurementForm()

    qs = Measurement.objects.all()
    context = {'form': form, 'measurement_list': qs}
    return render(request, 'index.html', context)

更新urls.py

from django.urls import path
from . import views


urlpatterns = [
    path('', views.new_measurement, name='index'),
]

不可能在一个中有更多的视图url,但是你可以模拟它。我这样做就像一个视图,在这个视图的模板中是 javascript,它用 AJAX 的响应加载第二个视图,并用第二个视图的内容填充所属元素。第二个视图不是整个模板,但它以一些 div 标签开始,这些标签被放置在第一个模板中。我会试着给你举个例子

观看次数

def first_view(request):
    return render(
        request,
        'first_template.html',
        {
            'first_content': 'Some heavy content'
        })


def second_view(request):
    return render(
        request, 
        'second_template.html', 
        {
            'second_content': 'Some heavier content!'
        })

first_template.html

...
<body>

    <div id="1">
        {{ first_content }}
    </div>
    <div>
        ... loading ...
    </div>

    <script>

    window.onload = function() {
        $.ajax({
            url: {% url 'to_second_view' %},
            method: 'GET',
            success: function(response) {
                $('#2').html(response);
            }
        })
    }

    </script>

</body>
...

second_template.html

<div>
    {{ second_content }}
</div>

如果您正在使用 cbv,您可以为继承 TemplateResponseMixin 和 return 的任何视图重写 get_template_names 方法,按顺序搜索字符串列表,直到匹配或ImporperlyConfigured 提出。例如:

class SomeView(TemplateResponseMixin):
   ...
   def get_template_names(self):
      if self.request.method == "POST":
         return ['post_template.html']
      else:
         return ['template.html']