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 %}
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.
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.
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).
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'),
]
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With