I create a table show book info from SQLite database and I'm trying to create an "Add New Book form" to make it add a new book into a table database. How can I add a book and then make it show into the table Book Info ?
<div class="container-fluid">
<!-- Add Book -->
<div class="add-book">
<h1>Add a Book</h1>
<form action="/add_book" method="POST" class="add_more_book">
{% csrf_token %}
<p>
<label for="title" id="title">Title:</label>
<input type="text" name="title" class="form-control" id="input-title" />
</p>
<p>
<label id="desc" for="desc">Description:</label>
<textarea class="form-control" name="description" id="input-desc" rows="3"></textarea>
</p>
<button type="submit" class="btn shadow btn-primary" id="addbtn">
Add
</button>
</form>
</div>
<!-- End of Add Book -->
<!-- Book info -->
<div class="book-info">
<form action="/" method="POST">
{% csrf_token %}
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for i in all_books_info %}
<tr>
<th scope="row">{{i.id}}</th>
<td>{{i.title}}</td>
<td>Views</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
</div>
Lets say you have an a table named Bio in your models.py file. Like so
class Bio(models.Model):
author = models.CharField(max_length= 20, null=True)
book = models.CharField(max_length= 20, null=True)
title = models.CharField(max_length=50)
desc = models.CharField(max_length=200)
Assuming you have imported you models at the top of you views.py file.
from .models import *
The * imports all the models from the models file.( There are reasons you may or may not want to import all the models in the future.)
In the views.py file
def processInfo(request):
print(request.POST["title"]
if len(str(request.POST["title"])) < 2:
print("Needs more the 2 characters to submit")
else:
print("Meets rule")
Bio.objects.create(title = request.POST["title"])
The print is there to see if anything is received. You always want to check first if you are not getting an empty string. I use len and other tools to check https://www.w3schools.com/python/ref_func_len.asp
There are a few ways on creating and getting data from the django models.
https://docs.djangoproject.com/en/3.0/topics/db/queries/
Finally for the function that renders "/" in the views.py file. Once you retrieve the data that you are looking for, return it with the request and html file.
Related
I am trying to get data from a table from an HTML that I created, that table has data from a table from a sqlite database.
So, for each checkbox marked in that table, I need to get the data from that row.
However, I am only receiving data from the first line, even if I mark several lines.
I've tried using the getlist, and creating an array, but without success. Since I am still learning from Flask and etc., I already looked for examples but I also couldn't find a solution.
My HTML table:
HTML code:
<form method="POST">
<table id="example" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>Id_Game</th>
<th style="width: 800px;">Game</th>
<th style="width: 100x;">Critic Score</th>
<th style="width: 100px;"><input type="checkbox" id="all" onclick="checkAll(this)"></th>
</tr>
</thead>
<tbody>
{% for game in games.items %}
<tr>
<td name="ID_GAME" id="ID_GAME">{{ game.ID_GAME}}</td>
<input type="hidden" name="ID_GAME" value="{{ game.ID_GAME }}" />
<td name="NM_GAME"> {{ game.NM_GAME}} </td>
<input type="hidden" name="NM_GAME" value="{{ game.NM_GAME }}" />
<td name="NR_CRITICSCORE">{{ game.NR_CRITICSCORE}}</td>
<td>
<input type="checkbox" id="one_checkbox" name="one_checkbox">
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if current_user.is_authenticated %}
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
{% else %}
<div class="form-group">
<button type="submit" class="btn btn-primary" onclick="submitoff()">Submit</button>
</div>
{% endif %}
</form>
Python code:
#main.route('/games/<int:page_num>', methods=('GET', 'POST'))
def games(page_num):
games = V_GAMES.query.paginate(per_page=10, page=page_num, error_out=True)
if request.method =='POST':
if request.form.getlist('one_checkbox'):
ID_USER = current_user.id
ID_GAME = request.form.get('ID_GAME')
NM_GAME = request.form.get('NM_GAME')
IC_PLAYED = "YES"
SYSDATE = datetime.datetime.now()
# create new user with the form data. Hash the password so plaintext version isn't saved.
addprofile = USERGAMESPLAYED(ID_USER=ID_USER, ID_GAME=ID_GAME, NM_GAME=NM_GAME, IC_PLAYED=IC_PLAYED, DT_PLAYED=SYSDATE)
# add the new user to the database
db.session.add(addprofile)
db.session.commit()
flash('Games have been successfully added to your profile.')
if not request.form.get('one_checkbox'):
flash('You have to check at least one game to add to your profile!')
return render_template('games.html', games=games)
In this two lines of code
ID_GAME = request.form.get('ID_GAME')
NM_GAME = request.form.get('NM_GAME')
You are always getting the data from the first line since you are using get but not gelist.
The way I would do this is to first modify your checkbox
<td>
<input type="checkbox" id="one_checkbox" name="one_checkbox" value="{{ your_game_id }}">
</td>
So that you can get all the games that are checked by their id
print(request.form.getlist('one_checkbox'))
[checked_game_id_1, checked_game_id_2, ...]
Then, use a for loop to loop through the checked games, use their id to get ID_GAME and NM_GAME, and do your processing.
EDIT
To get NM_GAME by ID_GAME
for id in request.form.get('one_checkbox')
game = V_GAMES.query.filter_by(ID_GAME=id).first()
nm_game = game.NM_GAME
I have a model 'Manifests' and a form 'CreateManifestForm'. The user enters multiple lines of data in the CreateManifestForm and these are saved to the Manifest model (on a line by line basis, not using ajax or anything).
There are 3 fields of concern in the model and form - 'Cases', 'FOB', 'CNF'. Both FOB and CNF are dollar amounts, so I'll use one as an example. How could I take the user entered FOB price, multiply it by cases and then store that number? Additionally, when the user enters another line, how could I do the same and then add that to the original number so I can get a total value.
MODELS.PY
class Manifests(models.Model):
reference = models.ForeignKey(Orders)
cases = models.IntegerField()
product_name = models.ForeignKey(Products, default=None, blank=True, null=True)
count = models.IntegerField()
CNF = models.DecimalField(max_digits=11, decimal_places=2, default=None, blank=True, null=True)
FOB = models.DecimalField(max_digits=11, decimal_places=2, default=None, blank=True, null=True)
def __str__(self):
return self.description
VIEWS.PY
def add_manifest(request, reference_id):
form = CreateManifestForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
instance = form.save(commit=False)
try:
order = Orders.objects.get(id=reference_id)
instance.reference = order
except Orders.DoesNotExist:
pass
instance.save()
form = CreateManifestForm(initial={'reference': Orders.objects.get(reference=reference_id)})
reference = request.POST.get('reference')
manifests = Manifests.objects.all().filter(reference=reference)
context = {
'form': form,
'reference_id': reference_id,
'manifests' : manifests,
}
return render(request, 'add_manifest.html', context)
ADD_MANIFEST.HTML
{% extends 'base.html' %}
{% block body %}
<div class="container">
<form id="create_mani_form" method="POST">
<br>
<br>
<br>
{% csrf_token %}
<div class="column">
<label for="form.reference" class="formlabels">Reference ID: </label><br>
<!-- <input type="text" value="{{ reference_id }}">-->
{{ form.reference }}
<br>
</div>
<div class="description">
<div class="column">
<label for="form.description" class="formlabels">Description: </label>
<br>
{{ form.product_name}}
</div>
</div>
<div class="column">
<label for="form.cases" class="formlabels">Cases: </label>
<br>
{{ form.cases }}
<br>
</div>
<div class="column">
<label for="form.count" class="formlabels">Count: </label>
<br>
{{ form.count }}
<br>
<label for="form.count" class="formlabels">CNF: </label>
<br>
{{ form.CNF }}
<br>
<label for="form.count" class="formlabels">Count: </label>
<br>
{{ form.FOB }}
</div>
<br>
<br>
<button type="submit" name="add_mani" style="border-color: #7395AE;">Add Line</button>
</form>
<br>
<h4>Manifest</h4>
<div class="table-responsive">
<!--<table id="manifest_table" class="table table-striped table-bordered table-sm " cellspacing="0"-->
<table class="table table-striped table-bordered manifest_table" cellspacing="0" style="width="100%">
<thead>
<tr>
<th style="width:2%;"</th>
<th style="width:10%;">Ref ID</th>
<th style="width:10%;">Cases</th>
<th style="width:60%;">Description</th>
<th style="width:10%;">Count</th>
<th style="width:10%">FOB</th>
<th style="width:10%">CNF</th>
</tr>
</thead>
<tbody>
{% for manifests in manifests %}
<tr>
<td>
Edit
</td>
<td>{{ manifests.reference }}</td>
<td>{{ manifests.cases }}</td>
<td>{{ manifests.product_name}}</td>
<td>{{ manifests.count}}</td>
<td>{{ manifests.FOB}}</td>
<td>{{ manifests.CNF}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="text-center">
Subit Manifest
</div>
<!-- Trigger the modal with a button -->
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
I would like to see a read-only field or something of that nature (I guess in the template) which shows the total for this particular manifest the user is creating. Any thoughts?
You can annotate the manifest objects with a computed field
from django.db.models import F, ExpressionWrapper
manifests = Manifests.objects.filter(
reference=reference
).annotate(
total=ExpressionWrapper(F('cases') * F('CNF'), output_field=DecimalField())
)
Then in your template you can reference manifest.total.
my django template is not submitting data! i know it is very basic thing but there is something i cannot realize here! my Model is:
class project(models.Model):
Project_Name = models.CharField(max_length=50)
And my ModelForm is:
class create_project(forms.ModelForm):
class Meta:
model = project
fields = ['Project_Name']
views.py
def project_create_view(request):
form = create_project(request.POST or None)
msg = ''
if form.is_valid():
form.save()
msg = 'Data Submitted'
form = create_project()
return render(request, 'create_project.html', {'form':form, 'msg':msg})
And my template is:
<form action="" method="POST">
{% csrf_token %}
<table border="1">
<tr>
<td>
<div>
<label for="id_Project_Name">Project Name</label>
<input type="text" name="Project_Name" id="id_Project_Name">
</div>
</td>
</tr>
</table>
<input type="submit" value="Submit">
</form>
My context dict is 'form', i tried so many ways searched online but no luck, can anyone help?...
I haven't pasted all the project as the case is similar for the rest fields.
In your html,
<form method="POST" action="#keep it blank or add action as per your requirement" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<span> {{field.errors}} </span>
<div> {{field}} </div> #you can add label or placeholder as per your requirement
{% endfor %}
<input type="submit" value="Submit">
</form>
You have not added enctype in your html.
Note : You can modify your views.
i managed to solve it this way after taking support from one of my experienced friends:
<td>
<div>
<label for="{{form.Project_Name.name}}">Project Name</label>
<input type="text" name="Project_Name" id="{{form.Project_Name.name}}">
</div>
</td>
EDIT 2: added the whole main-element in the HTML code
I'm building my own website with Python, HTML, CSS and Jinja. On this page I'm trying to build a function where users can post comments and reviews on the given recipe.
So, I'd like to post the following code but it gives this error message:
"?[1m?[31mPOST /recipes HTTP/1.1?[0m" 400 -
{% block main %}
<div id="recipe_id" style="display: none;" name="recipe_id">
{% for recipe in recipes %}
{{ recipe.recipe_id }}
{% endfor %}
</div>
<table class="table table-striped">
{% for recipe in recipes %}
<h1>{{ recipe.recipe_name }}</h1>
<a href= {{ recipe.link_to_recipe }} ><h4>Link to recipe</h4></a>
<h5>{{ recipe.category }}</h5>
<h5>{{ recipe.review }}</h5>
{% endfor %}
</table>
<div>
<textarea name="comments" id="comment" type="text" autofocus="autofocus" form="commentrating">Give your comment</textarea>
</div>
<h3>Rate the recipe!</h3>
<form action="/recipes" method="post" id="commentrating">
<fieldset>
<div id="review">
<select name="rating">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<br>
<div>
<input type="submit" id="button" value="Submit">
</div>
</fieldset>
</form>
<br>
<table class="table table-striped" id="comments">
<thead>
<tr>
<th colspan="1">Posted by</th>
<th colspan="3">Comment</th>
</tr>
</thead>
{% for comment in comments %}
<tr>
<td colspan="1">{{ comment.user }}</td>
<td colspan="3">{{ comment.comments }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
After three hours, I'm finally 'admitting' that I'm stuck on why it gives error 400 as it looks like all my other form actions. It shows 31mPOST while my other form action show a 37mPOST. Maybe this helps.
Anyone knows what I'm doing wrong and how I can fix this?
EDIT
I have also tried to find a bug in the python code, but cannot find the cause of the 400 error.
As the problem is probably in the server-side code, here is the code:
#app.route("/recipes", methods=["POST"])
#login_required
def recipes():
"""Function where the comment and rating is added to the recipe."""
if request.method == "POST":
#get the comment and/or rating
comment = request.form["comments"]
rating = int(request.form["rating"])
recipe = int(request.form["recipe_id"])
db.execute("INSERT INTO comments (recipe_id, comments, user) \
VALUES (:recipe_id, :comments, :user)", \
recipe_id=recipe, comments=comment, user=session["user.id"])
givenrating = db.execute("SELECT reviews, number_of_reviews FROM recipes WHERE \
recipe_id=:recipe", recipe=recipe)
# check if there already is given a rating
if givenrating[0]["number_of_reviews"] == "None":
db.execute("UPDATE recipes SET review=:rating, number_of_reviews=:numb \
WHERE recipe_id=:recipe", recipe=recipe, rating=rating, numb=1)
#load chosen recipe
recipes = db.execute("SELECT * FROM recipes JOIN categories ON \
recipes.category = categories.cat_id WHERE recipe_id=:recipe", recipe=recipe)
#load comments of the recipe
comments = db.execute("SELECT * FROM comments JOIN users on \
comments.user = users.id WHERE recipe_id=:recipe", recipe=recipe)
return render_template("recipe.html", recipes=recipes, comments=comments)
else:
number = int(givenrating[0]["number_of_reviews"])
ratings = int(givenrating[0]["reviews"])
# update existing rating
fullrating = ratings * number
newrating = fullrating + rating
number += 1
averagerating = newrating / number
db.execute("UPDATE recipes SET review=:review, number_of_reviews=:newnumber \
WHERE recipe_id=:recipe", review=averagerating, newnumber=number, recipe=recipe)
#load chosen recipe
recipes = db.execute("SELECT * FROM recipes JOIN categories ON \
recipes.category = categories.cat_id WHERE recipe_id=:recipe", recipe=recipe)
#load comments of the recipe
comments = db.execute("SELECT * FROM comments JOIN users on \
comments.user = users.id WHERE recipe_id=:recipe", recipe=recipe)
return render_template("recipe.html", recipes=recipes, comments=comments)
This error code is for Bad Request.
you are trying to get three elements(comments, rating and recipe_id), but they are not present in the form, so flask throws a 400 error.
what you could do is using hidden inputs to send that kind of information.
<form action="/recipes" method="post" id="commentrating">
<input type="hidden" name="recipe_id" value="{{ recipe_id }}">
<textarea name="comments" id="comment" type="text" autofocus="autofocus" form="commentrating">Give your comment</textarea>
<fieldset>
<div id="review">
<select name="rating">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<br>
<div>
<input type="submit" id="button" value="Submit">
</div>
</fieldset>
</form>
but, you should design your code differently, so that the recipe_id is set based on the recipe you want to add comment's for.
you can achieve that in numerous ways, but since that's not in the context of this question, i will leave that part alone.
another way to do is, using a JS code(jquery post or AJAX) to post the data, and that way, you could have make a variable with the data you want, and then post it.
I am trying to create an app where a user can manage a database of "Lost property" items. To do so I have a main page where all the items are displayed and I have a button per row to be clicked when the item is returned to the owner.
That button is submitting a form that should contain the ID value of the element that has been clicked so I trying to get something like
<input id="id_id" name="id" type="hidden" value="{{lostitem.id}}">
But I don't know how to pass that value to my form ! Here is my template :
{% for lostitem in lostitems %}
<tr>
<td>{{lostitem.id}}</td>
<td>{{lostitem.description}}</td>
<td>
<form class="give-back-item-form" method="POST">
{% csrf_token %}
{{formGiveBackItem.as_p}}
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
</button>
<!-- TRYING TO ADD A HIDDEN INPUT WITH THE ID AS VALUE -->
</form>
</td>
</tr>
{% endfor %}
Here is my form from forms.py
class GiveBackItemForm(forms.ModelForm):
id = forms.CharField(widget=forms.HiddenInput())
class Meta:
model = ItemLost
fields = ('id',)
And here is where I'm trying to get my $_POST['id'] and to update my object (I couldn't test this part as I'm not getting any POST information at the moment) :
from .forms import GiveBackItemForm
"""Defining our views"""
def item_list(request):
formGiveBackItem = GiveBackItemForm()
"""Ordering objects by date of creation"""
lostitems = ItemLost.objects.filter(added_date__lte=timezone.now()).order_by('added_date')
if request.method == "POST":
"""Giving back an item"""
itemToGive = ItemLost.objects.get(pk=request.POST.get('id'))
itemToGive.giveBackItem
"""Returning our ordered objects to the view"""
"""Request = everything we receive from the user (in a form for example)"""
return render(request, 'lostitem/item_list.html', {'lostitems': lostitems, 'formGiveBackItem' : formGiveBackItem})
Thanks for any help or remark about the code ! I'm just getting started and it was really hard to find anything helpful about my problem
EDIT : I managed to make it work by still using the Django ModelForm and the view to handle my form
Here is my code in my view :
def item_list(request):
"""Ordering objects by date of creation"""
lostitems = ItemLost.objects.filter(added_date__lte=timezone.now()).order_by('added_date')
"""To get data from the form"""
give_back_item_form = GiveBackItemForm(request.POST or None)
# check if form is valid
if give_back_item_form.is_valid():
itemToGive = ItemLost.objects.get(pk=give_back_item_form.cleaned_data['id'])
itemToGive.returned_date=timezone.now()
itemToGive.save()
# your rest of the code here
"""Returning our ordered objects to the view"""
"""Request = everything we receive from the user (in a form for example)"""
return render(request, 'lostitem/item_list.html', {'lostitems': lostitems, 'give_back_item_form' : give_back_item_form})
And here is the code for my template !
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<input type="hidden" name="id" value="{{ lostitem.id }}">
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"> </span>
</button>
</form>
Thank you all for your answers it lead me to the right solution !
If all you want to do is post back the id of an associated ItemLost object so that you can invoke a method on it (e.g., giveBackItem()), there's no need to use a ModelForm at all. Just use a normal HTML <form>, and manually put the hidden field in it:
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<button type="submit" value="Give Back">
<input type="hidden" name="id" value="{{lostitem.id}}">
</form>
So your complete template would become:
{% for lostitem in lostitems %}
<tr>
<td>{{lostitem.id}}</td>
<td>{{lostitem.description}}</td>
<td>
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
</button>
<input type="hidden" name="id" value="{{lostitem.id}}">
</form>
</td>
</tr>
{% endfor %}