I have two Django models:
from django.db import models
class Show(models.Model):
show_title = models.CharField(max_length=250)
def __unicode__(self):
return self.show_title
class ShowDates(models.Model):
show_date = models.DateTimeField(default=datetime.now)
show = models.ForeignKey(Show)
def __unicode__(self):
return str(self.show_date)
I am putting some Shows in the admin.py as well as some dates associated to the show.
from django.contrib import admin
from .models import Show, ShowDates
class ShowDatesInline(admin.StackedInline):
model = ShowDates
extra = 0
class ShowAdmin(admin.ModelAdmin):
list_display = ('show_title',)
inlines = [ShowDatesInline]
admin.site.register(Show, ShowAdmin)
This is working great for entering in the shows and their respective dates. I am confused as to how to display the dates as a form select field that are related to the show. I currently have the following in my views.py
from django.shortcuts import render
from django.core import urlresolvers
from .models import Show
from .forms import ShowDatesForm
def index(request, template):
shows = Show.objects.all()
return render(request, template, {
'shows': shows,
})
and here is the template using this code:
<table class='table'>
<thead>
<tr>
<th>Show Title</th>
<th>Show Date(s)</th>
</tr>
</thead>
<tbody>
{% for show in shows %}
<tr>
<td>{{ show.show_title }}</td>
<td>
<form action="." method="post">
{% csrf_token %}
<select name="attributes" class="required" required>
<option value="">---- Please Select ----</option>
{% for show_date in show.showdates_set.all %}
<option value="{{ show_date.show_date }}">
{{ show_date.show_date }}
</option>
{% endfor %}
</select>
</form>
</td>
</td>
{% endfor %}
</tbody>
</table>
I feel this is the wrong way to go about it. Can someone lend a hand as to how to display the show dates related to the proper show so that when a user saves this form, the proper show and showdate save?
If you use a ModelForm, django will handle all of that for you.
Related
views.py file
#student_blueprints.route("/update/<int:id>", methods=["POST", "GET"])
def update(id):
form = studentform()
st = student.query.filter_by(id=id).first()
if form.validate_on_submit:
st.name = request.form["name"]
st.course = request.form["course"]
db.session.commit()
return redirect(url_for("student.list"))
return render_template("update", form = form)
list.html file which is inside of templates/student
<tbody>
{% for i in range(0,students|length) %}
<tr>
<th scope="row">{{i}}</th>
<td>{{ students[i][1] }}</td>
<td>{{ students[i][2] }}</td>
<td>delete</td>
<td>update</td>
</tr>
{% endfor %}
</tbody>
forms.py
from flask import Flask
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField,IntegerField
class studentform(FlaskForm):
id = IntegerField("id")
name = StringField("name", name="name")
course = StringField("course",name="course")
submit = SubmitField("Submit")
update.html
<div class="container">
<form method="POST">
{{form.hidden_tag()}}
<div class="mb-3">
{{form.name.label(class="form-label")}}
{{form.name(class="form-control", name="name")}}
</div>
<div class="mb-3">
{{form.course.label(class="form-label")}}
{{form.course(class="form-control", name="course")}}
</div>
{{form.submit(class="btn btn-secondary")}}
</form>
</div>
In the above forms.py file for the name and course attributes i have added parameter called name="name" and name="course" to StringField. I want to access the name and course attribute from forms.py file inside of update method in views.py file as request.form['name'] and request.form['course'] to get their respective values from the form fields. I'm getting The browser (or proxy) sent a request that this server could not understand. KeyError: 'name' I was wondering how i could access the form fields dynamically so that i can do update operation? Thank you so much for your help
I am looking for the best way to make an updateable list from model objects in Django.
Let's say that I have a models.py:
class Foo(models.Model):
bar = models.CharField(max_length=10, blank=True)
foo = models.CharField(max_length=30, blank=True)
and I have a views.py that shows the objects from that model:
def my_view(request):
person_list = Person.objects.all()
ctx= {'person_list': person_list}
return render(request, 'my_app/my_view.html', ctx)
Then I have a template, my_view.html:
...
<table>
<tr>
<th>bar</th>
<th>foo</th>
<th></th>
</tr>
{% for item in person_list %}
<tr>
<td>{{item.bar}}</td>
<td>{{item.foo}}</td>
<td style="width: 5%;"><button type="submit" name="button">Change</button></td>
</tr>
{% endfor %}
</table>
...
So, I would like to add a form and make one of those fields changeable from within this template.
I would like users to be able to change item.foo and then click the change button and it sends the update to the model.
I tried making it a form, and using forms.py to create a form where users can put an input, and then submit the form, and that looked like this, my_view.html:
...
...
<table>
<tr>
<th>bar</th>
<th>foo</th>
<th></th>
</tr>
{% for item in person_list %}
<form method="post">
{% csrf_token %}
<tr>
<td>{{item.bar}}</td>
<td>{{item.foo}}</td>
<td>{{form.foo}}</td>
<td style="width: 5%;"><button type="submit" name="button">Change</button></td>
</tr>
</form>
{% endfor %}
</table>
...
...
And that was not working, because I couldn't figure out where to send the PK for that particular item in the Model.
Any help is appreciated.
You can do it using class-based views very easily
Say this is your models.py
class MyModel(models.Model):
alpha = models.CharField(max_length=200)
beta = models.CharField(max_length=200)
gama = models.CharField(max_length=200)
delta = models.CharField(max_length=200)
Your views.py should be like this
from django.views.generic import UpdateView
from .models import MyModel
class MyModelUpdateView(UpdateView):
model = MyModel
fields = ['beta'] # Include the fields you want to update form your template
As a reference, this will be your CreateView in views.py file
class MyModelCreateView(CreateView):
model = MyModel
template_name = 'myapp/myapp_form.html'
fields = ['alpha', 'beta', 'gama', 'delta']
This will be your urls.py
from .views import MyModelUpdateView
urlpatterns = [
....
path('app/<int:pk>/update/', MyModelUpdateView.as_view(), name='model-update'),
....
]
The default template for UpdateView is the one used for CreateView, myapp_form.html in this case. This will be your basic form template
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form }}
<button type="submit">Create</button>
</form>
{% endblock %}
I would like to update my list after adding some inputs through a form but i cannot see my updated list. I see the existing items in my list ,but when i add a new item it does not appear on the list. I can manually add it using the admin pannel and view it in the list(a whole different path),but not with the form i created to take input and update the list. I was able to query my database and input from the form is not getting written to the database, that's why its not displaying any changes.Below is my code
models.py
class BlogPost(models.Model):
notes = models.CharField(max_length = 1000000000000000000000000000)
date = models.DateTimeField(auto_now_add=True)
done = models.BooleanField(default=False)
def __str__(self):
return self.notes
form.py
from blog.models import BlogPost
class BlogForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['notes', 'done',]
views.py
from django.shortcuts import render,redirect
from django.http import HttpResponse,HttpResponseRedirect,HttpRequest
from blog.models import BlogPost
from blog.form import BlogForm
def home(request):
context = {
'welcome_text': 'Welcome to the home page. View some more stuff soon'
}
return render(request,'home.html', context)
def blogpost(request):
if request.method == "POST":
form = BlogForm(request.POST)
if form.is_valid():
if form.save():
message.success(request, "the task was added")
return redirect('blogpost')
else:
all_blogs = BlogPost.objects.all
return render(request, 'blog.html',{'the_blogs': all_blogs } )
blog.html
{%extends 'base.html' %}
{% block title%}
<title> Blog </title>
{% endblock title%}
{%block content %}
<div class="container">
<br>
{%for message in messages%}
{{message}}
{% endfor %}
<form method = 'POST'>
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" name = 'blog' placeholder = 'new blog' >
</div>
<button type="submit" class="btn btn-primary">Add Blog</button>
</form>
<br>
<table class="table table-hover table-dark">
<thead>
<tr>
<th scope="col">Blog </th>
<th scope="col">Done</th>
<th scope="col">Date</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
{% for item in the_blogs %}
{% if item.done %}
<tr class="table-success">
<td >{{item.notes}}</td>
<td >Not-Completed</td>
<td>{{item.date}}</td>
<td>edit</td>
<td>delete</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{%endblock content%}
if you need more information regarding this, here is a link to my GitHub repository with more code.
https://github.com/wfidelis/Django-App
You have to correct the code indentation and the get call part, pass the form to context object and call it with double curly brackets on templates, also add an action attribute to the template.
def blogpost(request):
all_blogs = BlogPost.objects.all()
if request.method == "POST":
form = BlogForm(request.POST)
if form.is_valid():
if form.save():
message.success(request, "the task was added")
return redirect('blogpost')
else:
form = BlogForm()
return render(request, 'blog.html',{'form': form, 'the_blogs': all_blogs } )
<form method='POST' action="">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Add Blog</button>
<form/>
When you add a blog, don't redirect, try rendering the page with the new list the same as how you did it here:
all_blogs = BlogPost.objects.all
return render(request, 'blog.html',{'the_blogs': all_blogs } )
or try returning new object created as JSON format to the front-end (as a response of the POST request) and front-end will add it to the HTML with jQuery or JS
I have a ListView that lists all questions from the Question model.
the models.py is:
class Question(models.Model):
question_text = models.CharField(max_length=200, unique=True)
pub_date = models.DateField(verbose_name='date published')
def __str__(self):
return self.question_text
now I want users can edit question_text. I tried this in views.py:
class UpdateDirectry(generic.list.ListView, generic.edit.FormMixin):
model = Question
template_name = 'accounts/editable_directory.html'
form_class = forms.EditListForm
def get_context_data(self, *, object_list=None, **kwargs):
context = super(UpdateDirectry, self).get_context_data()
context['object_list'] = Question.objects.filter(question_text__startswith='Who')
return context
and in the template:
<form method="post">
{% csrf_token %}
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Q</th>
<th scope="col">D</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td><input type="text" value="{{ object.question_text }}"></td>
<td>{{ object.pub_date }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<input type="submit" value="Submit">
</form>
I can edit the question_text but when I click submit button nothing happens (just a white page) and no records change in the database.
How can I really edit records with the submit button?
This is what the template shows:
Update 1: ## this is what I exactly want in view (this image is in admin with list_editable):
enter image description here
How can do the exact thing in a view?
Just use a ModelFormSetView from Django Extra Views:
from extra_views import ModelFormSetView
class UpdateDirectry(ModelFormSetView):
model = Question
template_name = 'accounts/editable_directory.html'
form_class = forms.EditListForm
and in your template:
<form method="post">
{{ formset }}
<input type="submit" value="Submit" />
</form>
You have to import UpdateView from :
from django.views.generic.edit import UpdateView
from django.views.generic.edit import FormMixin
from .forms import EditListForm
class UpdateDirectry(UpdateView, FormMixin):
model = Question
template_name = 'accounts/editable_directory.html'
form_class = EditListForm
I use Django to build a web app and when I submit a form, I got error:
AttributeError at /CustomerInfo/
'CustomerForm' object has no attribute 'first_name'
The project name is zqxt_views and app name is calc.
I create a file named forms.py in the calc folder, see below:
calc/forms.py:
from django import forms
class CustomerForm(forms.Form):
customer_id = forms.IntegerField(label="Customer ID")
first_name = forms.CharField(label="First Name", max_length=30)
last_name = forms.CharField(label="Last Name", max_length=30)
calc/views.py:
# -*- coding: utf-8 -*-
#from __future__ import unicode_literals
#from django.shortcuts import render
from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponseRedirect
import MySQLdb
from calc.models import Customer
from calc.forms import CustomerForm
from django.db import connection
...
def show_save_customer(request):
# if this is a POST request we need to process the form database
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CustomerForm(request.POST)
cursor = connection.cursor()
query = """ insert into customers (first_name, last_name) values (%s, %s) """
cursor.execute(query, [form.first_name, form.last_name])
# check whether it's valid:
if form.is_valid():
#process the data
return HttpResponseRedirect('AddressTableMaintain/');
else:
form = CustomerForm()
return render(request, 'CustomerInfo.html', {'form': form})
# Create your views here.
the form page like below:
calc/templates/CustomerInfo.html:
{% extends 'base.html' %}
{% block title %} Add and Show Customer details {% endblock %}
{% block content %}
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
</style>
<form action="{% url 'show_save_customer' %}" method="post">
{% csrf_token %}
<table width="50%" align="center">
<tr>
<td>Customer ID</td>
<td>
{{ form.customer_id }}
</td>
</tr>
<tr>
<td>First Name</td>
<td>
{{ form.first_name }}
</td>
</tr>
<tr>
<td>Last Name</td>
<td>
{{ form.last_name }}
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value = "OK" /></td>
</tr>
</table>
</form>
{% endblock %}
After I fill out some data and click the OK button, I always the error mentioned at the beginning, can someone tell me what's wrong with my code?
Indeed, forms do not expose their fields as attributes. You need to access the data via form.cleaned_data - which you should do after you have called form.is_valid().
form = CustomerForm(request.POST)
cursor = connection.cursor()
# check whether it's valid:
if form.is_valid():
query = """ insert into customers (first_name, last_name) values (%s, %s) """
cursor.execute(query, [form.cleaned_data['first_name'], form.cleaned_data['last_name']])
return HttpResponseRedirect('AddressTableMaintain/');
Note also however, unless you have a really good reason you should avoid raw SQL queries and use the Django model layer for your queries. In this case a ModelForm would be even more suitable as it would create and save the instance for you with a simple form.save().
Also note, you do anything on the form to show errors when the form is invalid. There are various ways of doing this, but at the very least you should put {{ form.errors }} in there somewhere.