SQLAlchemy with Flask does not commit - python

When I submit my form from webpage, I am not able to commit. Flashing data I need, I see they're there and correct, but something fails when committing. I am sure I am making a mistake somewhere because mostly commit are working except two. This is one of the two that is not working.
Models:
class Feedback(db.Model):
__tablename__ = 'feedback'
id = db.Column(db.Integer, primary_key = True)
rate = db.Column(db.Integer)
comment = db.Column(db.Text())
sender_id = db.Column(db.Integer)
receiver_id = db.Column(db.Integer)
Forms:
class LeaveFeedbackForm(Form):
rate = IntegerField('Rate', validators = [DataRequired(),
NumberRange(min = 1, max = 5, message = 'Rates admitted are only 1,2,3,4,5')])
comment = TextAreaField('Comment', validators = [DataRequired()])
submit = SubmitField('Submit')
Views:
#app.route('/leave_feedback/<sender>/<receiver>', methods = ['GET', 'POST'])
def leave_feedback(receiver, sender):
form = LeaveFeedbackForm()
rec = int(receiver)
sen = int(sender)
if form.validate_on_submit():
feedback = Feedback( rate = form.rate.data,
comment = form.comment.data,
receiver_id = rec,
sender_id = sen
)
db.session.add(feedback)
db.session.commit()
flash('Feedback Left Correctly.')
return redirect(url_for('index'))
flash(form.rate.data)
flash(form.comment.data)
flash(rec)
flash(sen)
return render_template('leave_feedback.html', receiver_id = receiver, sender_id = sender, form = form)
html:
{% block content %}
<div class="row">
<div class="large-6 columns">
<h1>Leave Feedback</h1>
</div>
</div>
<form action="" method="post" name="leavefeedback">
<div class="row">
<div class="large-6 columns">
<label>Rate
{{ form.rate }}
</label>
</div>
</div>
<div class="row">
<div class="large-6 columns">
<label>Comment
{{ form.comment }}
</label>
</div>
</div>
<div class="row">
<div class="large-6 columns">
<input class="button radius" type="submit" value="Leave Feedback">
</div>
</div>
</form>
{% endblock %}

You should add an else statement:
if form.validate_on_submit():
...
else:
for error in form.errors.itervalues():
flash(error[0])
Then you will get an error message from form.

I figured out my mistake, I simply forgot in my form:
{{ form.hidden_tag() }}

Related

Comment is not displaying in django after submission

I have tried to submit a comment from app rather than django admin. Comment is not displaying when submitted from my created app. But it is displaying when I add a comment from django admin app. May be I am doing something wrong in views.py file. Can anyone help me on this? Thank you.
views.py:
#login_required
def book_review(request,id):
book = get_object_or_404(Bookslist, id=id)
comment=Comment.objects.all().filter(post_id=id)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user_id = request.user
post.message= comment
post.save()
return redirect('book_review', id=id)
else:
form=CommentForm()
return render(request, "books/book_review.html", {'book':book, 'comment':comment, 'form': form})
models.py:
class Comment(models.Model):
message= models.TextField('Message',null=True)
date_comment=models.DateTimeField(default=now, null=True)
user_id= models.ForeignKey(User, on_delete=models.CASCADE,null=True)
post_id=models.ForeignKey(Bookslist,on_delete=models.CASCADE,null=True)
forms.py:
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['message', ]
book_review.html:
{% extends 'books/base.html' %}
{% load static %}
{% block stylesheet %}
<link rel="stylesheet" href="{% static 'accounts/accounts.css' %}">
{% endblock %}
{% block content %}
<div class = "container">
<ul class = "nav nav-tabs" id = "myTab" role = "tablist">
<li class = "nav-item">
<a class = "nav-link active" id = "summary-tab" data-toggle = "tab"
href = "#summary" role = "tab" aria-controls = "summary"
aria-selected = "true">Summary</a>
</li>
<li class = "nav-item">
<a class = "nav-link" id = "characters-tab" data-toggle = "tab"
href = "#characters" role = "tab" aria-controls = "characters"
aria-selected = "false">Characters</a>
</li>
<li class = "nav-item">
<a class = "nav-link" id = "relatedbooks-tab" data-toggle = "tab"
href = "#relatedbooks" role = "tab" aria-controls = "relatedbooks"
aria-selected = "false">Related Books</a>
</li>
</ul>
<div class = "tab-content" id = "myTabContent">
<div class = "tab-pane fade show active" id = "summary" role = "tabpanel"
aria-labelledby = "summary-tab"><br><br>
{{book.summary}}
</div>
<div class = "tab-pane fade" id = "characters" role = "tabpanel"
aria-labelledby = "characters-tab"><br><br>
{{book.c1}}<br><br>{{book.c2}}<br><br>{{book.c3}}<br><br>{{book.c4}}<br><br>{{book.c5}}<br><br>
{{book.c6}}<br><br>{{book.c7}}<br><br>{{book.c8}}<br><br>{{book.c9}}<br><br>
{{book.c10}}
</div>
<div class = "tab-pane fade" id = "relatedbooks" role = "tabpanel"
aria-labelledby = "relatedbooks-tab">Content for related books tab</div>
</div>
<br>
<br>
<div class="container">
<form method="post" class="mb-4">
{% csrf_token %}
<div class="form-group">
<label for="exampleFormControlTextarea1">Leave your comment:</label>
<textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-success">Post</button>
</form>
{% for com in comment %}
<div class="card mb-2">
<div class="card-body p-3">
<div class="row">
<div class="col-2">
<img src="{% static 'images/icon2.webp' %}" alt="{{ com.user_id }}" class="w-100">
<small>Posts: {{ com.count }}</small></div>
<div class="col-10">
<div class="row mb-3">
<div class="col-6">
<strong class="text-muted">{{ com.user_id }}</strong>
</div>
<div class="col-6 text-right">
<small class="text-muted">{{ com.date_comment }}</small>
</div>
</div>
{{ com.message }}<br><br>
{% if com.user_id == user %}
<button type="button" class="btn btn-primary">Reply</button>
{% endif %}
</div>
</div></div></div></div>
{% endfor %}
</div>
</div>
</div>
<!-- jQuery library -->
<script src = "https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity = "sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin = "anonymous">
</script>
<!-- Popper -->
<script src = "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity = "sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin = "anonymous">
</script>
<!-- Latest compiled and minified Bootstrap JavaScript -->
<script src = "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity = "sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous">
</script>
{% endblock %}
You need to add the post_id to the newly created comment.
Like so:
post.post_id = id
Also make sure you are using the correct naming for your variables i believe post should be comment in this scenario based on the form being of CommentForm: model = Comment
This replacement would make for sense for the code:
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.user_id = request.user
comment.message= comment
comment.post_id = id
comment.save()

Get multiple data from checkbox using "request.POST.get"

I tried to get multiple data from the checkbox using method below in my views.py:
if (((request.POST.get('data_choice ')) == ('Salary')) and ((request.POST.get('data_choice ')) and ((request.POST.get('data_choice ')) == ('Overtime')) ):
But the problem is the "and" condition is not working but if i use "or" condition it's work. May I know what's the problem with my code ? Is the request.POST.get can only get 1 data ?
choices.py
class DataChoices(models.TextChoices):
salary = 'Salary',_('Salary')
bonus = 'Bonus',_('Bonus')
allowance= 'Allowance',_('Allowance')
overtime= 'Overtime',_('Overtime')
models.py
class Data(models.Model):
Data_choices = Data_choices
data_choices = models.CharField(max_length=40,choices=Data_choices.choices,blank = True, null= True)
forms.py
class dataForm(forms.ModelForm):
datachoice = DataChoices
data_choice = forms.MultipleChoiceField(label=False,choices=datachoice .choices, required=True,widget=forms.CheckboxSelectMultiple(
attrs= {
"checked":"checked"
}))
class Meta:
model = Data
fields = ('__all__')
html
<form class="form" method="POST">
{% csrf_token %}
<fieldset class="form-group">
<h4 style="display:inline-block;" class="title-section">PRINT FORM</h4>
<div class="card">
<div class="card-body">
<div class="row col" >
<h5>Please select data to be included in the form</h5>
</div>
<div class="row mt-4">
<div class="col-lg">{{ form.data_choice |as_crispy_field }}</div>
</div>
</div>
<div class="col " style="text-align:center;">
<button class='btn btn-info btn-block'>Next</button>
</div>
</div>
</fieldset>
</form>
views.py
if form.is_valid:
data = {
'data_choice ':request.POST.get('data_choice '),
}
if (((request.POST.get('data_choice ')) == ('Salary')) and ((request.POST.get('data_choice ')) == ('Bonus')) ):
request.session['decision_data'] = data
return redirect ('printformA')
else:
messages.error(request, f'Error in creating Form')
return render(request, 'selectdata.html',context)
use QueryDict.getlist(key, default=None)
Usage:
data_choice = request.POST.getlist('data_choice')

Flask-SQLalchemy update the current_user

How would I update the current users firstname and lastnames in my Flask-SQLAlchemy database?
I have tried to use the following code based off of the flask-sqlalchemy documentation - however, it only commits the update for the email field and does not update the record for either the firstname or lastname fields.
# views.py
#users.route("/account", methods=['GET', 'POST'])
#login_required
def account():
form = UpdateUserForm()
if form.validate_on_submit():
current_user.firstname = form.firstname.data
current_user.lastname = form.lastname.data
current_user.email = form.email.data
db.session.commit()
return redirect(url_for('users.account'))
elif request.method == 'GET':
form.firstname.data = current_user.firstname
form.lastname.data = current_user.lastname
form.email.data = current_user.email
return render_template('account.html', form=form)
#forms.py
class UpdateUserForm(FlaskForm):
email = StringField('Email',validators=[InputRequired(message = 'Enter a valid email'),Email()])
firstname = StringField('First Name',validators=[InputRequired(message = 'Enter your first name')])
lastname = StringField('Last Name',validators=[InputRequired(message = 'Enter your last name')])
submit = SubmitField('Update')
def validate_email(self,email):
if User.query.filter_by(email=email.data).first():
raise ValidationError('This email has been registered already!')
# Summarized Template & Form Submission
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="account" role="tabpanel" aria-labelledby="account-tab">
<div class="col-5">
</div>
<div class="col-sm-12 col-md-7">
<form method="post" action="" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<div class="form-group">
<label class="small mb-0">{{ form.firstname.label }}</label>
{{ form.firstname(class="form-control") }}
</div>
<div class="form-group">
<label class="small mb-0">{{ form.lastname.label }}</label>
{{ form.lastname(class="form-control") }}
</div>
<div class="form-group">
<label class="small mb-0">{{ form.email.label }}</label>
{{ form.email(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
</div>
</div>
# Model.py
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer,primary_key=True)
selected_theme = db.Column(db.String(64),nullable=False,default='default')
email = db.Column(db.String(64),unique=True,index=True)
fullname = db.Column(db.String(64))
firstname = db.Column(db.String(64))
lastname = db.Column(db.String(64))
password_hash = db.Column(db.String(128))
def __init__(self,email,fullname,password, firstname, lastname):
self.email = email
self.fullname = fullname
self.firstname = firstname
self.lastname = lastname
self.password_hash = generate_password_hash(password)
def check_password(self,password):
return check_password_hash(self.password_hash,password)
def __repr__(self):
return f"Username {self.username}"
Sorry, I can't find a mistake. The following code works for me. Even if there is no real difference to yours, it is worth trying.
class UpdateUserForm(FlaskForm):
email = StringField(
'Email',
validators=[
# InputRequired is deprecated and replaced by DataRequired
DataRequired(message = 'Enter a valid email'),
Email()
]
)
firstname = StringField(
'First Name',
validators=[
DataRequired(message = 'Enter your first name')
]
)
lastname = StringField(
'Last Name',
validators=[
DataRequired(message = 'Enter your last name')
]
)
submit = SubmitField('Update')
def validate_email(self, email):
if User.query.filter_by(email=email.data).first():
raise ValidationError('This email has been registered already!')
#users.route("/account", methods=['GET', 'POST'])
#login_required
def account():
# You can forward your current data to the form here
form = UpdateUserForm(request.form, obj=current_user)
if form.validate_on_submit():
current_user.firstname = form.firstname.data
current_user.lastname = form.lastname.data
current_user.email = form.email.data
db.session.commit()
return redirect(url_for('users.account'))
return render_template('account.html', **locals())
<form method="POST">
{{ form.csrf_token }}
<div class="form-group">
{{ form.email.label() }}
{{ form.email(class='form-control') }}
{% if form.email.errors: %}
<div class="invalid-feedback">
{{ form.email.errors[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
{{ form.firstname.label() }}
{{ form.firstname(class='form-control') }}
{% if form.firstname.errors: %}
<div class="invalid-feedback">
{{ form.firstname.errors[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
{{ form.lastname.label() }}
{{ form.lastname(class='form-control') }}
{% if form.lastname.errors: %}
<div class="invalid-feedback">
{{ form.lastname.errors[0] }}
</div>
{% endif %}
</div>
{{ form.submit(class='btn btn-primary') }}
</form>
Thanks for your help! Was able to resolve my issue by including the following updated to ignore the email submission if it is unchanged (I think it was recognized as a duplicate record and preventing unique value). This little addition seems to resolve.
def validate_email(self,email):
if User.query.filter_by(email=email.data).first() and email.data != current_user.email:
raise ValidationError('Email has been already been registered.')

Unable to display form fields and objects in django

I am trying to create multiple forms in one template page(dischargedetails.html) using different views. Each form model is having foreignkey Ipd,First form (ProcedureForm) is working fine but the in Second form(investigation Form) not able to display investigation date feild and investigation name field
models.py :
class Investigation(models.Model):
id = models.AutoField(primary_key = True)
ipd = models.ForeignKey(Ipd,on_delete = models.DO_NOTHING)
name = models.CharField(max_length=60)
report = models.TextField(max_length=500)
date = models.DateField(("Date"), default=datetime.date.today)
class Procedure(models.Model):
id = models.AutoField(primary_key = True)
ipd = models.ForeignKey(Ipd,on_delete = models.DO_NOTHING)
report = models.TextField(max_length=500)
date = models.DateField(("Date"), default=datetime.date.today)
time = models.TimeField( blank=True,default=now)
urls.py :
re_path(r'^(?P<ipd_id>\d+)/dischargedetails/$', my_patient.discharge_detail, name='discharge_details'),
views.py:
#login_required
def discharge_detail(request,ipd_id):
object = get_object_or_404(Ipd,pk=ipd_id)
if request.method =="POST":
procedure = ProcedureForm(request.POST)
if procedure.is_valid():
procedure.save()
return HttpResponseRedirect(request.path_info)
else :
return HttpResponse(procedure.errors.as_data())
else :
prolist=Procedure.objects.all().filter(ipd=ipd_id)
procedure = ProcedureForm()
return render(request, 'dischargedetails.html',{'object':object,'procedure':procedure,'prolist':prolist})
if request.method=="POST":
investigation = InvestigationForm(request.POST)
if investigation.is_valid():
inves = investigation.save(commit = False)
inves.object = object
inves.save()
return HttpResponseRedirect(request.path_info)
else:
return HttpResponse(investigation.errors.as_data())
else :
investigationlist = Investigation.objects.all().filter(ipd=ipd_id)
investigation = InvestigationForm()
return render(request, 'dischargedetails.html',{'object':object,'investi':investigation,'investilist':investigationlist})
#login_required
def create_investigation(request,ipd_id):
object = get_object_or_404(Ipd,pk=ipd_id)
template
<form method="post" action="{% url 'discharge_detail' ipd_id=object.ipd_id %}" enctype="multipart/form-data">
<label>Date</label>
<div class="input-group date">
{{ investi.date| add_class:'form-control' }}
<label id="addNotesIDhelp" class="error" for=""></label>
</div>
<div class="form-group">
<textarea id="notesTextId" name = "report" type="text" placeholder="Add Investigation"class="form-control" value = "{{investi.report}}" required></textarea>
<div class="form-group">{{investi.name | add_class:'form-control'}} <label>Report Name</label></div>
</div>
{% for pro in investilist %}
<div class="media">
<div class="shadow w-100 p-3 mb-5 bg-white rounded">
<div class="media-body" style="background-color: rgb(173, 181, 212)">
<h4 class="media-heading">{{pro.name}}{{pro.date}}</h4>
<br>
<p style="color: black">{{pro.report}}</p>
<br>
</div>
</div>
</div>
{% endfor %}

How to compare a database foreign key value with form foreign key value in Django?

I have a Django project and I encountered with a problem of comparing a database foreign key attribute with form foreign key attribute. My project files are below :
My Model.py File:
class Teacher(models.Model):
Name = models.CharField(max_length=100)
Designation = models.CharField(max_length=100,choices=DESIGNATION)
Department = models.CharField(max_length=100,choices=T_Dept)
Address = models.CharField(max_length=100)
def __str__(self):
return self.Name + ", " + self.Designation + ", " + "("+self.Department +"), "+ self.Address
class Moderation(models.Model):
year = models.CharField(max_length=100,choices=T_Year)
semester = models.CharField(max_length=100,choices=T_Semester)
examtype = models.CharField(max_length=30,choices=EXAMTYPE)
examyear = models.CharField(max_length=30,choices=EXAMYEAR)
NamAdd = models.ForeignKey(Teacher, on_delete=models.CASCADE)
position = models.CharField(max_length=100,choices=POSITON)
def __str__(self):
return unicode(self.NamAdd)
My forms.py File :
class modaForm(forms.ModelForm):
class Meta:
model=Moderation
fields=[
'year',
'semester',
'NamAdd',
'position','examtype','examyear'
]
My HTML File :
<form action="{% url 'modIni' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-sm-12 col-md-4">
<br>
<div class="input-group">
<span class="input-group-addon">Year </span>
{% load widget_tweaks %}
{{ modForm.year|add_class:"form-control" }}
</div>
</div>
<div class="col-sm-12 col-md-4">
<br>
<div class="input-group">
<span class="input-group-addon">Semester </span>
{% load widget_tweaks %}
{{ modForm.semester|add_class:"form-control" }}
</div>
</div>
<div class="col-sm-12 col-md-4">
<br>
<div class="input-group">
<span class="input-group-addon">Exam Type</span>
{% load widget_tweaks %}
{{ modForm.examtype|add_class:"form-control" }}
</div>
</div>
<div class="col-sm-12 col-md-4">
<br>
<div class="input-group">
<span class="input-group-addon">Exam Year</span>
{% load widget_tweaks %}
{{ modForm.examyear|add_class:"form-control" }}
</div>
</div>
<div class="col-sm-12 col-md-4">
<br>
<div class="input-group">
<span class="input-group-addon">Name and Address</span>
{% load widget_tweaks %}
{{ modForm.NamAdd|add_class:"form-control" }}
</div>
</div>
<div class="col-sm-12 col-md-4">
<br>
<div class="input-group">
<span class="input-group-addon">Position </span>
{% load widget_tweaks %}
{{ modForm.position|add_class:"form-control" }}
</div>
</div>
<div class="col-sm-12 col-md-12">
<br>
<center>
<button type="submit" class="btn btn-success btn-lg"><spam class="glyphicon glyphicon-send"> </spam> Submit</button>
</center>
</div>
</form>
My View.py File :
def modIni(request):
modForm = modaForm(request.POST or None,request.FILES or None)
year = modForm['year'].value()
semester = modForm['semester'].value()
examtype = modForm['examtype'].value()
examyear = modForm['examyear'].value()
NamAdd = modForm['NamAdd'].value()
position = modForm['position'].value()
fMod = Moderation.objects.all().last
if modForm.is_valid():
instance = modForm.save(commit=False)
flag =True
for obj in Moderation.objects.all():
if obj.year == year and obj.semester == semester and obj.examtype == examtype and obj.examyear == examyear and obj.NamAdd == NamAdd and obj.position == position:
context = {'fMod':fMod,'modForm':modForm,'msg':"<span style='color:red;'><h3>Already Inserted!</h3> Last entry : </span>"}
flag = False
break
if flag:
instance.save()
#modForm = modaForm()
context = {'NamAdd':NamAdd,'fMod':fMod,'modForm':modForm,'msg':"<span style='color:#4BB543;'><h3>successfully accomplished!</h3> Last entry : </span>"}
else:
context = {'fMod':fMod,'modForm':modForm,'msg':"<span style='color:Red;'> <center>Please fill in all the fields</center>Last entry : </span>"}
return render(request, 'tbs/form/modaration.html',context)
How to compare obj.NamAdd.Name == NamAdd in view File? Please help me by providing any hint.
Basically, I want to save a unique Moderation object into database How doing this? Has any alternative way?
Thanks advance.
Whats wrong with obj.NamAdd == NamAdd ?
Many.
The primary issue for the comparison failure is that NamAdd is an integer(Teacher object id) where obj.NamAdd is a model object.
So, on this regard, it should be obj.NamAdd.id == NamAdd
Don't do this please. Not that way. You are bypassing input validation.
It could be obj.NamAdd == modForm.cleaned_data['NamAdd']
Since you want unique Moderation,
add this to the model:
class Meta:
unique_together = (('year', 'semester', 'examtype', 'examyear', 'NamAdd', 'position'))
so that it now looks like
class Moderation(models.Model):
year = models.CharField(max_length=100, choices=[])
semester = models.CharField(max_length=100, choices=[])
examtype = models.CharField(max_length=30, choices=[])
examyear = models.CharField(max_length=30, choices=[])
NamAdd = models.ForeignKey(Teacher, on_delete=models.CASCADE)
position = models.CharField(max_length=100, choices=[])
def __str__(self):
return unicode(self.NamAdd)
class Meta:
unique_together = (('year', 'semester', 'examtype', 'examyear', 'NamAdd', 'position'))
(remember makemigrations and migrate)
**note I used empty list for choices, adjust for your case.
now in the view, use this for checking moderation existence:
moderation_exists = Moderation.objects.filter(year=modForm.cleaned_data['year'], semester=modForm.cleaned_data['semester'],examtype=modForm.cleaned_data['examtype'], examyear=modForm.cleaned_data['examyear'], NamAdd=modForm.cleaned_data['NamAdd'], position=modForm.cleaned_data['position']).exists()
if moderation_exists:
context = {'fMod': fMod, 'modForm': modForm,
'msg': "<span style='color:red;'><h3>Already Inserted!</h3> Last entry : </span>"}
flag = False

Categories