Django form field issue with model formset - python

I'm having an issue with rendering individual form fields in a template. I have a model formset that I'm re-ordering after creation to make displaying a little easier on the template. Nothing too complicated, but rendering the form fields isn't working. You can see in the template where I try and render {{ form.train }}, but nothing shows up in the output. However, the form is definitely there because {{ form.instance.user.name }} works correctly.
I opened up PDB and inspected the form variable that I'm adding into the dictionary, and it says <django.forms.widgets.ScheduleForm object at 0x10c58bc50>. I'm not sure if that helps or not, but I wanted to provide as much info as possible.
The Model Form
class ScheduleForm(ModelForm):
class Meta:
model = models.Schedule
fields = [
'train',
'semi',
'tri_axle',
'flow_boy',
'misc',
'material',
'notes'
]
views.py
formset_fields = ('train','semi','tri_axle','flow_boy','misc','material','notes')
ScheduleFormSet = modelformset_factory(models.Schedule, fields=formset_fields, extra=0)
formset = ScheduleFormSet(queryset=queryset)
# Getting form in the right format
ordered_forms = {}
for form in formset:
# Make sure the job exists on the object
if not form.instance.job.number in ordered_forms:
ordered_forms[form.instance.job.number] = {}
# Make sure the user exists on the object
if not form.instance.user.name in ordered_forms[form.instance.job.number]:
ordered_forms[form.instance.job.number][form.instance.user.name] = []
# Append to correct place.
ordered_forms[form.instance.job.number][form.instance.user.name].append(form)
# Dict will look like
# { 'jobID' : { 'user' : [form1,form2,form3] } }
Template
{% for job, users in ordered_forms.items %}
<h2>{{ job }}</h2>
{% for user, forms in users %}
<table class='table striped'>
<thead>
<tr>
<th>{{ user }}</th>
<th>Train</th>
<th>Semi</th>
<th>Tri-Axle</th>
<th>Flow Boy</th>
<th>Misc</th>
<th>Material</th>
<th>Notes</th>
<th></th>
</tr>
</thead>
<tbody>
{% for form in forms %}
<tr>
<td>{{ form.instance.broker.name }}</td>
<td>{{ form.train }}</td>
<td>Semi</td>
<td>Tri-Axle</td>
<td>Flow Boy</td>
<td>Misc</td>
<td>Material</td>
<td>Notes</td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endfor %}

Turns out I forgot to add .items to {% for user, forms in users %}.
{% for job, users in ordered_forms.items %}
<h2>{{ job }}</h2>
{% for user, forms in users.items %}
<table class='table striped'>
....
{% endfor %}
{% endfor %}

Related

context must be a dict rather than module

When I am filtering for my search bar I am getting this error. I am not sure what I am doing wrong here
Watching this tutorial: https://www.youtube.com/watch?v=llbtoQTt4qw&t=3399s
views.py
class pplList(LoginRequiredMixin,ListView):
model = People
context_object_name = 'people'
def get_context_data(self, **kwargs):
search_input = self.get.GET.get('search-area') or ''
if search_input:
context['people'] = context['people'].filter(name__icontains=search_input)
return context
people_list.html
{%if request.user.is_authenticated %}
<p>{{request.user}}</p>
Logout
{% else %}
Login
{% endif %}
<hr>
<h1>Interviewee Dashboard {{color}}</h1>
Add Candidates
<form method="get">
<input type = 'text' name = 'search-are'>
<input type = 'submit' value = 'Search'>
</form>
<table>
<tr>
<th> Item</th>
<th> </th>
</tr>
{% for people in people %}
<tr>
<td>{{people.name}}</td>
<td>View</td>
<td>Edit</td>
<td>Delete</td>
</tr>
{% empty %}
<h3>No items in list</h3>
{% endfor %}
</table>
There are some minor mistakes such as it should be self.request.GET.get('search-area'), also you haven't called the super() method, so try this view:
class pplList(LoginRequiredMixin,ListView):
model = People
context_object_name = 'people_list'
def get_context_data(self, **kwargs):
context=super().get_context_data(**kwargs)
search_input = self.request.GET.get('search-area', False)
if search_input:
context['people']= People.objects.filter(name__icontains=search_input)
return context
In the Html, the field name search-are and you are accessing in the view as self.request.GET.get('serach-area', False) kindly change its name to search-area` in the input tag of Html.
Also, class based views are generally written in PascalCase as they are classes of Python and requires their name to be written as model name as prefix and actual view name as suffix, so it should be PeopleListView.

django "<QuerySet{[ ]}" appearing in list

I have been wrestling with something that I think is a bonehead oversight on my part. I have a form that feeds an input to a view that queries some SQL tables I have and returns a list back with columns from each table**.
The odd thing that is happening is the my list is appearing with
<QuerySet{[ ]}>
brackets around each list object. Can anyone tell me how to avoid this?
Much appreciated.
**I am using this list to combine these tables rather than ForeignKeys because I was having a terrible time getting my SQL databases to populate correctly using SQLAlchemy and Postgres and read that there were known issues with that, so I gave up on that method.
views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.views import generic
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import *
from .forms import QuoteForm, RfqForm
def bom_result(request):
if request.method == 'POST':
form = RfqForm(request.POST)
if form.is_valid():
bom_list = []
rfq = {}
rfq_search = form.cleaned_data['rfq_entered']
rfq['rfq_num'] = rfq_search
rfq['bom'] = Quotereq.objects.values('bom_entered').filter(rfq_num__exact=rfq_search)
rfq['part_num'] = Bom.objects.values('partnum').filter(bom__exact='07-00-000019')
bom_list.append(rfq)
context = {'bom_list': bom_list}
return render(request, 'quote/result.html', context)
else:
return HttpResponse("<h1>Something Went Wrong</h1>")
else:
form = RfqForm()
context = {'form': form}
return render(request, 'quote/lookup.html', context)
result.html
{% extends "base.html" %}
{% load static %}
{% block title %}{{title}}{% endblock title %}
{% block sidenav %}
{% for page in page_list %}
<li>
{{page.title}}
</li>
{% endfor %}
{% endblock sidenav %}
{% block content %}
{% autoescape off %}
{{ content }}
{% endautoescape %}
{% if bom_list %}
{% for bom in bom_list %}
<table>
<tr>
<th><h1>RFQ Number</h1></th>
<th><h1>BOM</h1></th>
</tr>
<tr>
<td>
<ul style="list-style-type:none">
<li>{{ bom.rfq_num }}</li>
</ul>
</td>
<td>
<ul style="list-style-type:none">
<li>{{ bom.bom }}</li>
</ul>
</td>
<td>
<ul style="list-style-type:none">
<li>{{ bom.part_num }}</li>
</ul>
</td>
</tr>
</table>
{% endfor %}
{% else %}
<p>No Matching RFQ in Database</p>
{% endif %}
{% endblock content %}
Here is what the table outputs:
If we look at what part_num is, we see:
rfq['part_num'] = Bom.objects.values('partnum').filter(bom__exact='07-00-000019')
This is a QuerySet, a QuerySet is some sort of query that results in a set of objects. You construct such QuerySets by using the Django ORM (what you do here).
In order to obtain the elements in the QuerySet, you can iterate over the elements, and for example individually process these.
In the template we can for example write:
<td>
<ul style="list-style-type:none">
<li>{% for part in bom.part_num %} {{ part.part_num }} {% endfor %}</li>
</ul>
</td>
So we iterate over the QuerySet, we then each time obtain a dictionary (that was wrapped in the QuerySet, and we render the value that corresponds to the 'part_num' key in the dictionary. Of course we can make it more sophisticated (for example use HTML markup directives, like {% for part in bom.part_num %} <b>{{ part.part_num }}</b> {% endfor %} to put it in boldface.
I am using this list to combine these tables rather than ForeignKeys because I was having a terrible time getting my SQL databases to populate correctly using SQLAlchemy and Postgres and read that there were known issues with that, so I gave up on that method.
I would really advice to use ForeignKeys, ManyToManyFields, etc. to represent relations between entities. Not only will Django allow you to make more expressive queries, it also will add constraints to the database such that columns that correspond to a ForeignKey will always point to the primary key of the table where they point at, etc. In case you for example remove a referred entity, you can define triggers what to do (remove related objects, set the foreign key columnn to NULL, etc.). Perhaps following the Django tutorial can provide some required information to proceed.
Of course you are free to design and implement the project in the way you like, but my personal experience is that it will probably in the end result in more trouble.

URL Patterns and Views

I have an application which requests data based on certain parameters. I use two functions to handle the requests and then create two objects from the responses. I am able to iterate through each object individually and display the data of a particular object on my webpage, but when I try to use both functions simultaneously, only one function iterates through the object. It is my understanding that this issue has something to do with URL patterns, but I am not as to what the best approach would be. Below you will find my urlpatterns, my functions, and the HTML I use to access the view.
urls.py
urlpatterns = [
path('', views.customer, name='customer'),
path('', views.information, name='information'),
]
views.py
def customer(request):
for i, contact in enumerate(contactObj):
try:
contacts = contactObj
context = {'contacts': contacts}
except KeyError:
print()
return render(request, 'uccx/home.html', context)
def information(request):
for i, ticket in enumerate(ticketObj):
try:
tickets = ticketObj
context = {'tickets': tickets}
except KeyError:
print()
return render(request, 'uccx/home.html', context)
home.html
<tbody>
{% for ticket in tickets %}
<tr class="{% cycle 'row1' 'row2'">
<td> {{ ticket.id }} </td>
<td> {{ ticket.company.name }} </td>
<td> {{ ticket.summary }} </td>
</tr>
{% endfor %}
</tbody>
Your URL patterns should be different for every view. otherwise, it will always call the view which is defined above either you call it by customer or information
So your URL patterns should be
urlpatterns = [
path('customer/', views.customer, name='customer'),
path('information/', views.information, name='information'),
]
UPDATE
You don't have to create separate views for fetching objects from different tables to
show in a webpage
Create a single view and send as many objects in context dictionary.
def table_content(request):
...
# fetch objects here from model
contacts = Contact.objects.all()
tickets = Ticket.objects.all()
# set objects to context dictionary
context = {'contacts': contacts, 'tickets' : tickets}
return render(request, 'uccx/home.html', context)
Now in your template, you can easily loop over tickets and contacts
{% for ticket in tickets %}
<tr>
<td> {{ ticket.id }} </td>
...
</tr>
{% endfor %}
{% for contact in contacts %}
<tr>
<td> {{ contact.id }} </td>
...
</tr>
{% endfor %}

How can I get the edited values corresponding to the keys of a dictionary in views.py POST method, passed as a context variable in Django template?

I'm basically trying to develope a Sudoku Solver in Django, and in template I have created a table of 9X9 having the empty cells initially. I want the users to edit those cells and generate a puzzle and submit.
And I want to read that puzzle on POST method but just couldn't do it after searching a lot. And pardon me if it is so obvious as I've just started learning Django.
logic.py
global table
table = {}
for i in range(9):
for j in range(9):
key = 'i'
key = key + str(i)+str(j)
table[key]=0
views.py
from .logic import table
# Create your views here.
def sudokuf(request):
title = "Sudoku Puzzle"
if request.method == 'POST' :
print(request.POST) # here I want to read the puzzle data and solve it
return render (request,"sudoku.html",table)
sudoku.html
<form method="POST" action=""> {% csrf_token %}
{% include "table.html" %}
<input type="submit" align="centre" value="Solve">
</form>
table.html
<table class="sudoku" align="center">
<tr>
{% if i00 %}
<td id="i0_0" class="static">{{i00}}</td>
{% else %}
<td id="i0_0" class="edit"><input id="i00" maxlength="1" autocomplete= "off"></td>
{% endif %}
{% if i01 %}
<td id="i0_1" class="static">{{i01}}</td>
{% else %}
<td id="i0_1" class="edit"><input id="i01" maxlength="1" autocomplete= "off"></td>
{% endif %}
{% if i02 %}
<td id="i0_2" class="static">{{i02}}</td>
{% else %}
and so on....
But I'm getting the same dictionary as I sent(with all 0s as value), as context variable, after clicking 'Solve'.
Firstly, you need to actually look in request.POST:
if request.method == 'POST' :
print(request.POST) # not 'table'
But secondly, your form fields do not have name attributes, so they won't even be sent in the POST to begin with. You need to add those attributes:
<input id="i00" name="i00" maxlength="1" autocomplete= "off"

Indexing a QuerySet array in django templates

I'm trying to access a queryset array that I passed from the views in the templates. I want to index each entry using a numeric iterator. I'm using a django snippet to get the range of customers. Here is what I have done so far:
{% for cust in customer_comments %}
{% for i in cust|length|get_range %}
<tr>
<td>{{cust.i.customer_id}}</td>
<td>{{cust.i.feedback_detail}}</td>
</tr>
{% endfor %}
{% endfor %}
When I iterate using cust.i.customer_id it displays nothing. But when I use cust.0.customer_id or cust.1.customer_id, it displays what I want it to. Kindly help why i is not working.
Btw this is how I initialized the customer_comments object in views.
customer_comments = []
for i in all_features:
if OpenFeedback.objects.filter(feature_id = i.feature_id).exists():
feedback_obj = OpenFeedback.objects.filter(feature_id = i.feature_id)
customer_comments.append(feedback_obj)
You don't iterate like that in Python or in Django templates: you iterate through the list itself.
{% for customer in cust %}
<tr>
<td>{{customer.customer_id}}</td>
<td>{{customer.feedback_detail}}</td>
</tr>
{% endfor %}

Categories

Resources