No value returned in django powered HTML - django

Looked for the solution for almost 2 days without luck - any guidance is much appreciated.
Given 'views.py' looks like this (all needed lib are imported properly):
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from django.template.context_processors import request
from django.views import generic
class HomeView(generic.TemplateView):
template_name = 'polls/djIndex.html'
def test(request):
data = {'temperature': '53F', 'state': 'NY', 'mood': ['good', 'bad']}
return render(request, 'polls/djIndex.html',{'data':data})
These are not working (no value returned) on djIndex.html:
test #1:
{% for key, value in data.items %}
<h3>{{key}}-----: {{value}}</h3>
{% endfor %}
test #2:
{% for key in data.items %}
<p>Value of Key 1 : data["temperature"]</p>
{% endfor %}
test #3
{% for key, value in data %}
<p>Key {{ key }}, Value {{ value }}</p>
{% endfor %}
test #4
<h2> context2: {{data.temperature}}</h2>
But these are working on djIndex.html:
<h2> Temperature: {{temperature}}</h2>
<h2> State: {{state}}</h2>
<h2> Mood: {{mood}}</h2>
Ask: How to make those non-working test #1-#4 to work on my HTML page. Especially test #3 and #4. Am I doing something wrong in my Django config, as some of those test #1-#4 are accepted answers in some forums in different instances?

To pass some context to the template from a class-based TemplateView you can override its get_contecxt_data()
Give this a try
class HomeView(generic.TemplateView):
template_name = 'polls/djIndex.html'
def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
context['temperature'] = '53F'
context['state'] = 'NY'
return context
Why didn't it work before
TemplatView or any other class-based views don't have a test() method to handle requests, so your test method wouldn't get called upon a request.

Related

Django-filters FilterView shows empty list on page load

So I want to link to a given page that has filters on it, and have it display every item in the table before I click search, and only stop displaying items when bad input is given. My problem is similar to the following problem, with a few differences. Empty result list on django-filter page startup
The differences being the poster's default behavior is my desired behaviour and I am using class based views, not functional views.
My urls:
from django.urls import path
from . import views
app_name = 'advising'
urlpatterns = [
path('', views.MyList.as_view(), name='MyList'),
]
my views:
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import generic
from django.template import loader
from .models import *
from django_filters.views import FilterView
from .filter import *
class MyList(FilterView):
template_name = 'advising/MyList.html'
context_object_name = 'tables'
filterset_class = MyFilter
def get_queryset(self):
return Table.objects.order_by('Name')
my filter:
import django_filters
from .models import Table
class MyFilter(django_filters.FilterSet):
Name = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = Table #The table this form will reference
fields = ["Name"]
my template:
<form method="get">
{{ filter.form.as_p }}
<button type="submit">Search</button>
</form>
{% if tables %}
<ul>
{% for table in tables %}
<li>{{table}}</a></li>
{% endfor %}
</ul>
{% else %}
<p>Nothing to see here!.</p>
{% endif %}
Is there any way to mimic the behavior of searching for an empty string when the page first loads?
To be very specific, I want the url advising/ to have the same behaviour as the url advising/?Name=
Right now advising/ always gives me an empty list
Finally found a post with the same issue I'm having (no idea why it was never coming up on Google) where the issue was solved. It's as simple as adding the line "strict = False" in my view.
This is the question I found that answered it for me:
Display all record on django-filter page startup

django, views direct to a another html page

I am using Django for develop a website. The website is intended to use to search information stored in a MySQL database.
This is the current basic flow of the web site.
1) index.html - this has a form to select an option
2) according the option, users will redirect to search.html (include a form)
3) once the user provides the criteria, the result will be displayed in reply.html
In my views.py , I have two functions.
from django.shortcuts import render
from website.models import WebsiteRepository
from .forms import SearchForm
from .forms import SelectTypeForm
def Search(request):
if request.method == 'POST':
#do something
return render(request, 'reply.html', {'env_dict':env_dict})
else:
#do something
return render(request, 'search.html', context = context)
def index(request):
if request.method =='POST':
#do something
return render(request, 'search.html', context = context)
else:
#do something
return render(request, 'index.html', context= context)
When I go to index.html page, I can select a option and it will direct me to search.html. After, I fill the form there and submit, it wont give me the reply.html page.
I have a feeling that, I could make this work by changing urls.py.
from django.urls import path
from website import views
urlpatterns = [
path('', views.index, name='index'),
#path('search/', view.Search, name ='Search')
]
I tried to google it. But its too much details and Iam kind of lost.
Do any of you guys know how to achieve this?
Thanks
search.html
{% extends "base_generic.html" %}
{% block content %}
<h3>Welcome to search information Repository</h3>
<form method="post">
{% csrf_token %}
{{form.as_p}}
<button type = 'submit'>submit</button>
</form>
{% endblock %}
index.html
{% block content %}
<h3>Welcome to information Repository</h3>
<form method="post">
{% csrf_token %}
{{form.as_p}}
<button type = 'submit'>submit</button>
</form>
just for clarify things more, ill add the forms.py too
from django import forms
from .models import WebsiteRepository
class SearchForm(forms.Form):
websiterepository = WebsiteRepository
env_indicators = websiterepository.objects.filter (key_aspect='Environmental').values_list('repo_id','indicator')
indicator = forms.ChoiceField(choices=env_indicators,label = 'Indicator' )
OPTIONS = (('2000','2000'),('2001','2001'),('2002','2002'), ('2003','2003'),('0000','0000'),)
year = forms.ChoiceField(choices=OPTIONS)
class SelectTypeForm(forms.Form):
OPTIONS = (('1', 'Envirnmental Indicators'),('2','Economic Indicators'),('3','Social Indicators'),)
types = forms.ChoiceField(choices=OPTIONS)
Your code is wrong on many points.
First thing first: for a search, you want a GET request, not a POST (POST is for updating the server's state - adding or updating your database mostly). This is the semantically correct method (since you want to GET data), and it will allow a user to bookmark the url.
Second point: you don't want to submit the search form to the index view but to the search view. No need for redirects etc, just use the {% url %} templatetag to fill the action attribute of your form (you of course need to have a 'Search' url in your urls.py):
<form method="get" action="{% url 'Search' %}">
{% csrf_token %}
{{form.as_p}}
<button type = 'submit'>submit</button>
</form>
if you want to have this form on more than one page (which is often the case for search forms), use an inclusion tag tha will take care of creating an unbound SearchForm and render the template fragment.
Then in your search view, you only want GET requests, and do not use two different templates, this will only lead to useless duplication.
def Search(request):
form = SearchForm(request.GET)
# use the form's data - if any - to get search results
# and put those results (even if empty) in you context
return render(request, 'reply.html', {'env_dict':env_dict})
And finally, your search form is totally broken:
class SearchForm(forms.Form):
# this is totally useless
websiterepository = WebsiteRepository
# this will only be evaluated once at process startup, so you will
# get stale data in production - and probably different data
# per process, in a totally unpredictable way.
# You need to either put this in the form's __init__ or wrap it
# in a callable and pass this callable
env_indicators = websiterepository.objects.filter (key_aspect='Environmental').values_list('repo_id','indicator')
indicator = forms.ChoiceField(choices=env_indicators,label = 'Indicator' )
# are you going to manually add a new year choice every year ???
OPTIONS = (('2000','2000'),('2001','2001'),('2002','2002'), ('2003','2003'),('0000','0000'),)
year = forms.ChoiceField(choices=OPTIONS)
For the "indicators" ChoiceField you want something like:
def get_indicators_choices():
return Websiterepository.objects.filter (key_aspect='Environmental').values_list('repo_id','indicator')
class SearchForm(forms.Form):
# IMPORTANT : we are NOT calling the function here, just
# passing it (python functions are objects) to the field, which
# will call it everytime the form is instanciated, so you don't
# have stale data
indicator = forms.ChoiceField(
choices=get_indicator_choices,
label='Indicator')
As a last note: be consistent with your namings (ie why name one view in all lower (index) and capitalize the other (Search) ? Whichever convention you choose (I strongly suggest respecting pep8 here), at least stick to it for the whole project.
The problem is that code is not redirecting to /search, instead rendering search.html after post from index.html.
Try doing like-
views.py-
#your code
def index(request):
#do something
if request.method == 'POST':
return redirect('Search')
else:
#render index.html
def search(request):
#do something
if request.method == 'POST':
#render reply.html
else:
#render search.html
Another way to achieve this is if you specify action in your form so that form posts on /search.
search.html
<form method="post" action="/search">
{% csrf_token %}
{{form.as_p}}
<button type = 'submit'>submit</button>
</form>

Django w/ Apache, CSRF Verification Failing

I have a bit of an issue with CSRF verification in my Django app. I have two other {% csrf_token %} tags in my app, in two different HTML templates. These work fine, and always have. When attempting to add a third in another new template though, I receive the '403 Forbidden' page. I've copied the style of the two working 'post' commands exactly, but for some reason this one will not work. Any suggestions?
The 'post' form contains a single select/drop-down object, and a submit button. Clicking the button should direct to a view to process the posted data, written again just like the first 2, but it throws the 403 error instead, with the reason for failure being 'CSRF token missing or incorrect'. I'm running Django 1.4.22 also, with User authentication enabled. Here is the not-working view:
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
...Other Views...
#login_required
def Process(request, id):
...
try:
choice = request.POST['choice']
except(KeyError, Item.DoesNotExist):
return render_to_response('app/home.html', context_instance=RequestContext(request))
else:
...Process posted data...
return HttpResponseRedirect(reverse('app.views.display', args=()))
Here is the working view:
#Same includes/imports as earlier, in same file
#login_required
def Submit(request, id, id_2, data):
try:
new_data = request.POST[data.name]
except(KeyError, DataPoint.DoesNotExist):
return render_to_response('app/home.html', context_instance=RequestContext(request))
else:
...Process new data...
return HttpResponseRedirect(reverse('app.views.Data_View', args=()))
And here is the HTML file:
<!DOCTYPE html>
...
<table>
<tr><td>
<form action="/app/page/to/redirect/to/" method="post">
{% csrf_token %}
<select name="choice">
<option name="yes" value="yes" selected>Yes</option>
<option name="no" value="no">No</option>
</select>
</form></td></tr>...</table>

Reverse error in Django 1.10

I'm new to Django and slowly learning how it works. I just upgraded to 1.10 and part of my app stopped working. I know it is related to the changes made into Reverse. I have been reading and I cannot find exactly what I'm doing wrong. Almost everything works as it should with a couple of exceptions. The behavior is as follows:
1) On my app I load reservations/create, it works perfectly I can create my reservation
2) When I click create, the reservation is actually created and saved into the database, but the browser is sent to the wrong address. It gets sent to reservations/create instead of reservations/reservation number (for example reservations/2 where it shows its details) and shows a Reverse error (included in this post)
3) If I test reservations/2 for example, it shows that it was actually created.
4) Also if a go straight to reservations/ it should show a list of all the ones already create, but instead shows a Reverse error too.
I would really appreciate any help in understanding what I'm doing wrong.
Models.py
class Reservation(models.Model):
res_number = models.AutoField(primary_key=True)
date = models.DateField(default=datetime.date.today())
status = models.CharField(max_length=10,default="Created")
reservation_type = models.CharField(max_length=11,choices=shced_type_choices, default="rental")
aircraft = models.ForeignKey('aircraft.Aircraft')
renter = models.CharField(max_length=30,blank=False,null=False)
instructor = models.CharField(max_length=30,blank=True,null=False)
def get_absolute_url(self):
return reverse("reservations:detail", kwargs={"res_number": self.res_number})
Main urls.py
url(r'^reservations/', include('dispatch.urls', namespace='reservations')),
Dispatch.urls
from django.conf.urls import include, url
from django.contrib import admin
from .views import (
reservations_list,
reservations_detail,
reservations_edit,
reservations_dispatch,
reservations_close,
reservations_cancel,
reservations_create,
reservations_close,
)
urlpatterns = [
url(r'^$', reservations_list),
url(r'^(?P<res_number>\d+)/$', reservations_detail),
url(r'^(?P<res_number>\d+)/edit/$', reservations_edit),
url(r'^(?P<res_number>\d+)/dispatch/$', reservations_dispatch),
url(r'^(?P<res_number>\d+)/close/$', reservations_close),
url(r'^(?P<res_number>\d+)/cancel/$', reservations_cancel),
url(r'^create/$', reservations_create),
url(r'^close/$', reservations_close),
]
Views.py
from django.contrib import messages
from django import forms
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from .forms import ReservationForm, CloseReservationForm
from .models import Reservation
def reservations_list(request):
queryset = Reservation.objects.all()
context = {
"object_list": queryset,
"title": "List of Reservations:"
}
return render(request, "dispatch/list.html", context)
def reservations_detail(request, res_number=None):
instance = get_object_or_404(Reservation, res_number=res_number)
context = {
"title": instance.renter,
"instance": instance,
}
return render(request, "dispatch/details.html", context)
def reservations_create(request):
form = ReservationForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
print(instance.aircraft.hobbs)
instance.save()
messages.success(request, "Reservation Created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
return render(request, "dispatch/create.html", context)
Details.html
{% extends "dispatch/base.html" %}
{% block head_title %}{{ block.super }} | {{instance.res_number}}{% endblock head_title %}
{% block content %}
<h1>Reservation for {{title}} on {{instance.date}}</h1>
Reservation Number: {{instance.res_number}}</br>
Date: {{instance.date}}</br>
Status: {{instance.status}}</br>
Reservation Type: {{instance.reservation_type}}</br>
Aircraft: {{instance.aircraft}}</br>
Renter's Name: {{instance.renter}}</br>
Instructor's Name: {{instance.instructor}}</br>
Expected Flight Hours: {{instance.expected_hours}} Hrs</br>
Actual Flown Hours: {{instance.flown_hours}} Hrs</br>
Reservation Created on: {{instance.created}}</br>
Last Updated on: {{instance.updated}}</br>
{% endblock content %}
Create.html
{% extends "dispatch/base.html" %}
{% block head_title %}{{ block.super }} | Create{% endblock head_title %}
{% block content %}
<h1>Create Reservation</h1>
<form method='POST' action=''>{% csrf_token %}
{{form.as_p}}
<input type="submit" name="Create Reservation">
</form>
{% endblock content %}
Reverse error screenshot
Your problem is your routes don't have names. So when you are using reverse('some_name'), you have to have such name defined. The name is detail in your case, so you want to do something like this (see the parameter name)
urlpatterns = [
url(r'^(?P<res_number>\d+)/$', reservations_detail, name='detail'),
]
Also please don't insert traceback as a screenshot. You see the link 'switch to copy-and-paste view'? Yeah, use that the next time.

User Context in Django

I am having problems with user authentication for my django site. I have a log-in screen that seems to work. When the user clicks log-in, I call the django.contrib.auth.login and it seems to work fine. However on subsequent pages have no knowledge that there is a user logged in. Example {% user.is_authenticated %} is false. There are also some menu functions that I want to be available for logged in users such as my-account and logout. Those functions are not available, except on the log-in page. Which is really strange.
This seems to be a user context problem. But I'm not sure how I am supposed to be passing a context around to ensure that my login is stable. Does anyone know at could be going on here? Any advice?
---------part of base.html------------
<!--- The following doesn't register even though I know I'm authenticated -->
{% if user.is_authenticated %}
<div id="menu">
<ul>
<li>My Customers</li>
<li>Customer Actions</li>
<li>My Account</li>
</ul>
</div>
{% endif %}
---------my views.py -----------------
# Should I be doing something to pass the user context here
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
c = Context({
'customer_list': customer_list,
})
t = loader.get_template(template)
return HttpResponse(t.render(cxt))
If you're using Django 1.3, you can use the render() shortcut, which automatically includes RequestContext for you.
from django.shortcuts import render
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
return render(request, "path_to/template.html",
{'customer_list': customer_list,})
In this case, you could go one step further, and use the generic ListView:
from django.views.generic import ListView
class CustomerList(Listview):
template_name = 'path_to/template.html'
queryset = Customer.objects.all().order_by('lastName')[:5]
Use a RequestContext.
As Daniel Suggested, use the RequestContext... or better, just use the render_to_response shortcut:
from django.template import RequestContext
from django.shortcuts import render_to_response
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
return render_to_response(
"path_to/template.html",
{'customer_list':customer_list,},
context_instance=RequestContext(request))