Flask + SqlAlchemy delete database entries - python

I have to delete database entries conditionally and I couldn't figure out as the form is asking for correct parameters posted in uri. I can delete entries in shell with same code but not in view. Following is the view and form:
#app.route('/cancelannualsub/<int:student_id>', methods=['DELETE'])
def cancel_yearly_rec(student_id):
if not user_authorized():
return redirect('/')
user = get_profile_data(session['auth_token'])
profile_data = user['StudentProfile']
pkg = Package.query.filter_by(student_id=profile_data.id).first_or_404()
if request.method=='POST':
try:
pkg = Package()
dbase.session.delete(pkg)
flash('Package deleted successfully.')
dbase.session.commit()
except:
pass
return redirect('plans')
return render_template('profile/cancel/cancel.html')
Form:
<form action="{{ url_for('cancel_yearly_rec', student_id=***can't render value here***) }}" method='post'>
<input type='hidden' name='_method' value='DELETE'
<input class='btn' type="submit" value="Cancel" />
</form>
I am trying different things from stackoverflow examples. Please assist if I am doing something wrong or if there is a better way to do it.

I wasn't using proper formatting to render model objects inside try block.
It supposed to be something like:
mymodel = Model.query.filter_by(variable=some_field_data).first_or_404()
dbase.session.delete(mymodel)
dbase.session.commit()
For readers don't get confused with "dbase" because I made this import like:
from app import db as dbase
You can import it simply by:
from app import db
or add "as anything".
Then you reference anything in rest of your file where you've made import.

Related

Python: Sending to a certain URL based on form submission

I'm trying to create a search bar where it will send users to certain URLs based on the query they typed on the "result" page, e.g. "/results?<form_search>". I've successfully made the version where the result page URL is /results but this isn't really what I want.
Here's the HTML script:
<!--index.html-->
<form action="{{ url_for('search') }}" method="post">
<input type="text" id="search" name="form_search" placeholder="Type here">
</form>
Here's the Python script where I direct the result to /results URL:
#app.py
#app.route("/")
def index():
return render_template("index.html")
...
# I want to direct this to "/results?<form_search>"
# I think I need to put the line below somewhere but I'm not sure where
# form_search = request.form.get("form_search")
#app.route("/results", methods=["POST"]) # Want to change it to "/results?<form_search>"
def search(form_search):
...
return render_template("results.html", form_search=form_search, results=results)
Anyone can help?
I barely worked with flask but if you want to have the dynamic URL you need to add it in your #app.route decorator, e.g.: If I want a username to be posted in the URL this is what it would look like:
#app.route("/<username>") # str,int,uuid,float,path also works
def user_name(username=None, post_id=None):
return render_template("index.html", name=username)
When it comes to getting the data from the form I can show you a similar example as I did in django (I didnt work with flask a while so you might need to experiment a bit yourself) - This is a method as it is created in a class:
def get_queryset(self):
query = self.request.GET.get(
"searchrecipe") # searchrecipe is the name of our input form, means: the value we enter in the form -> This might also work for FLASK, get the data with request.get and FORM NAME
object_list = Recipe.objects.filter(name__icontains=query) #This filters the data in my database (aftger name) so not relevant for you
return object_list

Django - Class Function not returning page

I am trying to create code for my Django site which will take the user's input, perform a calculation, and then send the data back to the user in the form of a new page, however everytime I run the code, it does not create the new page nor does it post the results.
Below is the function itself.
def SparkCalc(request):
new_item = sparkCalculator()
new_item.tix = request.POST['tix']
new_item.tenrolls = request.POST['tenrolls']
new_item.crystals = request.POST['crystals']
new_item.save()
total = new_item.getTotal()
return render(request, 'SparkResults.html', {"title": "Spark Results"}, {"total": total})
and below is the Django page I am calling it from:
<form action="/SparkCalc/" method="POST">{% csrf_token %}
<label for ="tix">Please enter your single roll tickets</label>
<input type="text" id="tix" name="tix"/>
<label for ="tenrolls">Please enter your ten-roll tickets</label>
<input type="text" id="tenrolls" name="tenrolls"/>
<label for ="tix">Please enter your total crystal amount</label>
<input type="text" id="crystals"name="crystals"/>
<input type="submit" value="Get Results"/>
</form>
And finally below is the class I created:
class sparkCalculator(models.Model):
tix = models.PositiveIntegerField()
tenrolls = models.PositiveIntegerField()
crystals = models.PositiveIntegerField()
def getTotal(self):
return (int(self.tix)*300) + (int(self.tenrolls)* 3000) + int(self.crystals)
The way I envision the code to work is that once the user enters their information into the form, Django then runs the SparcCalc function, collecting the information entered, performing the math and collecting a total, and then sending the total to the new page. Instead, it seems to be just refreshing the page.
Also is it possible to run this style of code without creating an entire class for it? This is not information I would want to store. Ideally I would just want it executed at runtime and to be done with it, but previous attempts at doing this have failed and I simply gave up and tried creating a class.
As far as I can tell it is correctly entered into my urlpatterns.
from catalog.views import (
SparkCalc,
sparkCalcPage,
)
urlpatterns = [
path('SparkCalc/', sparkCalcPage),
path('SparkResults/', SparkCalc),
]
Any help would be greatly appreciated and thank you in advance for your help.
The signature of render function is as follows:
def render(request, template_name, context=None, content_type=None, ...):
...
In your case, you have passed {'total':total} to the content_type keyword argument instead of context.
# also make sure 'SparkResults.html' can be found by the template loader
render(request, 'SparkResults.html', {"title": "Spark Results", "total": total})
Also, you need to submit your data to the corrent view.
<form action="/SparkResults/" method="POST">
{% csrf_token %}
...
</form>
Instead of creating a model for the task,
perform the operation in the views.py itself.
def SparkCalc(request):
tix = request.POST['tix']
tenrolls = request.POST['tenrolls']
crystals = request.POST['crystals']
total = (int(tix)*300) + (int(tenrolls)* 3000) + int(crystals)
return render(request, 'SparkResults.html', {"title": "Spark Results"}, {"total": total})

Using flask form result to generate a URL?

I am creating an app that does some analysis, given a user enters in some IDs into the form. For example, if a user types 12345, 23456 into the TextField form, the app will run some analysis on these IDs and then display the results. My problem is that currently, when the user clicks "Submit" and the data analysis completes, it always redirects the user to www.website.com/results. I need to create unique url's like www.website.com/results/12345+23456 so that 1) I can have multiple users and 2) users can send this link to people to re-generate the analysis.
Now, there are some questions on StackOverflow that are similar to my question but they are not the same and did not help me. So first, let me show some code before discussing that.
I have a home page which contains the the form:
<div>
<form action="https://website.com/results/" class="form-inline" method="post">
<div class="form-group">
<label for="PubmedID">Pubmed ID(s)</label>
<input type="text" class="form-control" id="PubmedID" name="pmid" value="{{request.form.pmid}}">
</div>
<button type="submit" id= "myButton" class="btn btn-default" data-toggle="modal" data-target="#myModal">Submit</button>
</form>
</div>
As you can see, the value for the form is request.form.pmid. My Flask-Wtform for this is here:
class pmidForm(Form):
pmid = TextField('PubmedID')
Since the action of this form points towards website.com/results that triggers my Flask function to be called:
#app.route('/results/', methods=["POST"])
def results():
form = pmidForm()
try:
if request.method == 'POST':
#entry = request.form or request.data doesn't help me...
entry = form.pmid.data #This is the user input from the form!
# DO LOTS OF STUFF WITH THE ENTRY
return render_template('results.html')
except Exception as e:
return(str(e))
As you can see I am using POST and form.pmid.data to get the data from the textfield form.
Again, I don't want to just redirect to /results, I'd like to expand on that. I tried to modify my form so that the form action pointed to https://website.com/results/{{request.form.pmid}}/ and then update the results function to be
#app.route('/results/<form_stuff>', methods=["POST"])
def results(form_stuff):
But this never worked and would re-direct me to a 404 not found page. Which I believe makes sense because there is no form data in the action when the HTML is first rendered anyway.
Now, the other post that mine is similar to is: Keeping forms data in url with flask, but it quite doesn't answer or solve my problem. For tthis post, the key point that people made was to use POST (which I already do), and to obtain and return the data with return request.args['query']. For me, I'm already processing the form data as I need to, and I have my return render_template() exactly how I want it. I just need to add something to the results URL so that it can be unique for whatever the user put into the form.
What do I need to add to my form in the html and to my Flask /results function in order to have the form data added into the URL? Please let me know if there's any other information I can provide to make my problem more clear. I appreciate the help! Thanks
This isn't really a question about Flask.
If you want the data to show in the URL when you submit the form, you should use method="get" rather than "post". Then the URL will be in the form https://website.com/results/?pmid=12345.

Can make a Search with a template form work

I use crispy-forms in all of my search,but in this one I need to do it with a template form, I don't know what's wrong with my code 'cause I have the same code in other project and it works fine, I don't know if is the Django version, currently I'm using 1.8. The error that I get is Page not found (404), I doesn't find the url.Here's my code hope you can help me. I use q and param in the url but none works.
urls.py
url(r'^search/(?P<param>\S+)$', permission_required('agenda.change_agenda', login_url='/no_access')(SearchContact.as_view()), name='searchcontact'),
template_form.html
<form class="well form-search" action="/search/" method="get">
<input type="text" class="input-medium search-query" name="param">
<button type="submit" class="btn">Search</button>
</form>
views.py
class SearchContact(ListView):
template_name = 'agenda_contacts.html'
def get_queryset(self):
query = self.request.GET.get('param')
return Agenda.objects.filter(name=param)
Your regex
r'^search/(?P<param>\S+)$
matches urls like /search/hello or /search/my-search.
However, your search form is sending the search terms in the GET paramters, for example /search/?param=hello or /search/?param=my-search.
GET parameters are not captured in urls.py. You can access them with request.GET in the view as you are already doing.
Therefore, you should remove param from the regex, and change your url pattern to the following.
url(r'^search/$', permission_required('agenda.change_agenda', login_url='/no_access')(SearchContact.as_view()), name='searchcontact'),

How to use hidden input in an html form with Python+Jinja2

When I put this line in my html template, I can successfully pass the input string via a jinja2 variable into my Python code...
<label for="firstName">First name*</label>
<input type="text" name="fname" id="firstName" value="{{ fname }}">
However, when I attempt to pass a hidden input with the following line...
<input type="hidden" name ="contact_form" value="{{ active_form }}">
... I'm not seeing the value pass back to my Python code. I've not learned Javascript yet. Is there some Javascript required to pass hidden input values? What am I missing?
I recommend using WTForms.
Example
from wtforms import TextField, validators, PasswordField, TextAreaField, HiddenField
class ArticleCreateForm(Form):
title = TextField('Title', [validators.Required("Please enter title.")],
filters=[strip_filter] )
body = TextAreaField('Body', [validators.Required("Please enter body.")],
filters=[strip_filter])
category = QuerySelectField('Category', query_factory=category_choice )
person_name = HiddenField()
views.py
#app.route('/create', methods=['GET', 'POST'])
def article_create():
if 'email' not in session:
return redirect(url_for('signin'))
person = Person.query.filter_by(email=session['email']).first()
name = person.firstname
article = Article()
form = ArticleCreateForm()
form.person_name.data = person.firstname
if form.validate_on_submit():
form.populate_obj(article)
db.session.add(article)
db.session.commit()
return redirect(url_for('index'))
return render_template('create.html', form=form, person=person, name=name)
I know this is an old post but I was fooling around with a Jinja template and I wanted solve this particular issue since I was dealing with it myself. I was planning on fooling Jinja by passing in my value and adding the quote symbols (") in a concatenated string along with my Jinja variable (named "ticket_number") like so:
<input class="hidden" name="ticket_number" value={{ ticket.ticket_number + '"' }}>
That will NOT work. So I removed the concatenation and passed the variable in directly. This seemed promising. Was expecting to find the HTML code would contain the variable value without the quote symbols surrounding up but was presently surprised to find that either Jinja or Flask quoted the variable correctly with no extra add on's using the straight variable value:
<input class="hidden" name="ticket_number" value={{ ticket.ticket_number }}>
The variable itself is an integer so I confirmed if this also happens with regular alphanumerical string variables. Let me know if it works for you all-
If you are using Flask along with Jinja2 (which I would recommend), you can run code like this in the view function:
from flask import request
#app.route('/path/to/submit/page', methods=["GET","POST"])
def viewfunctionforsubmitpage():
request.form['contact_form']
Flask is a nice, lightweight, and built using Jinja2, so that is good.

Categories

Resources