Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 %}
like image 544
nameisxi Avatar asked Feb 11 '18 09:02

nameisxi


People also ask

How do I link views and urls in Django?

A request in Django first comes to urls.py and then goes to the matching function in views.py. Python functions in views.py take the web request from urls.py and give the web response to templates. It may go to the data access layer in models.py as per the queryset.

Can we create multiple views in Django?

Yes, this works not only for views.py but also for models.by or tests.py . See this excellent answer for more details. I still leave this answer here, because I would like to mention that large files could also indicate that you might want to split your single app into multiple apps.

What happens when a URL is matched Django?

Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL, matching against path_info . Once one of the URL patterns matches, Django imports and calls the given view, which is a Python function (or a class-based view).


2 Answers

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'),
]
like image 115
Sagar Avatar answered Sep 22 '22 12:09

Sagar


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.

like image 45
Navid Zarepak Avatar answered Sep 21 '22 12:09

Navid Zarepak