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

20,027

Solution 1

You can't map multiple views in one url but you can do mutiple works in one view. update your views.py as you can see that I am sending (querylist and form) both in that view

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)

update urls.py

from django.urls import path
from . import views


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

Solution 2

You can't call 2 views for one url. basically each url has to be linked to one view and that's something you can't really change.

But if you want your code to be cleaner and have multiple functions, you can call them in your view, basically what you can do is to make a view and call it when a url or even more than one url has been used and in that view decide which function to use

Example:

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

This is a very simple example but you can do so many other things.

Share:
20,027
nameisxi
Author by

nameisxi

Updated on March 27, 2022

Comments

  • nameisxi
    nameisxi about 2 years

    I'm trying to show forms defined by new_measurement on index.html, but I only manage to get IndexView() to work. I tried various combinations between IndexView() and new_measurement(), but those didn't work out at all. I know that IndexView() doesn't pass anything related to new_measurement(), and new_measurement() isn't called, which is the core of my problem. I'd really appreciate if someone more experienced with Django could tell me what I could, or should do. Thank you.

    Here's my 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 %}
    
  • nameisxi
    nameisxi about 6 years
    I liked this solution a lot, it's very clean, but I couldn't get it to work. I got this error when calling IndeView(): __init__() takes 1 positional argument but 2 were given. I don't understand what's wrong since it looks good to me?
  • Navid Zarepak
    Navid Zarepak about 6 years
    Well i don't know what your code s but it's not related to this solution. it's a simple way. if you get errors in your code you probably should check for mistakes. You're basically calling another function and returning what that function will return. Nothing complicated really.
  • Gokul nath
    Gokul nath almost 4 years
    Thanks, It helps! How can I implement incase I want to use the class based view instead of function based view. Just opposite to your answer?