Searching with a defined query in Django / Python - python

Currently as it stands I have a search bar and a button on my homepage like so.
<div class="input-group">
<input id="address" type="textbox" placeholder="City or Zipcode" class="form-control">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="addressSearch">Search</button>
</span>
</div>
I have created a api.py file which is within my websites folder which looks like so.
import urllib2
import json
locu_api = '****'
def loc_search(query):
api_key = locu_api
url = 'https://api.locu.com/v1_0/venue/search/?api_key=' + api_key
locality = query.replace(' ', '%20')
final_url = url + "&locality=" + locality + "&category=restaurant"
json_obj = urllib2.urlopen(final_url)
data = json.load(json_obj)
for item in data['objects']:
print item['name']
print item['phone']
Essentially what I am trying to do is when the user search's for a city e.g. New York then the loc_search(query) is called populating the search field '(query)' with the users input and the data then being displayed.
I haven't much experience with either django or api's so any help would be invaluable. Thanks again

i'm not really experienced in django too, but have been working around for 3 months now, i will advise you to make use of the django-auto-complete-light or django-ajax-selects for your frontend search in the navigation bar, and django-salmonela for your backend fields. those are helpful. and the input tag doesn't really work with your django forms, so you'll have to use a class in your div tag and explicitly call each form field using the {{ form.fieldName }} then make use of the widget to reference your template tags, or just use the above packages which know much better how to handle your fields.
example:
within your template:
<div class="container text-center form-horizontal topSpace">
<form method="POST" enctype="multipart/form-data" action="{% url 'create-recipe' %}">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="form-group">
{{ form.name.errors }}
<label for="{{ form.name.id_for_label }}" class="col-lg-4 control-label">Name:</label>
<div class="col-lg-1">
{# <input type="text" class="form-control" id="user-name" placeholder="Enter your name">#}
{{ form.name }}
</div>
</div><!-- end form-name-->
{{ form.as_p }}
<input type="submit" value="Add Recipe">
</form>
</div>
then in your form:
class RecipeForm(autocomplete_light.ModelForm, forms.ModelForm):
class Meta:
model = Recipe
exclude = []

Related

How to combine two dictionaries in Python without duplicates

Hey I'm trying to combine two dictionaries filled with JSON data without duplicates. I'm using Flask and Jinja2 to build an api to fetch json data from an api and post it on a web page, I want to be able to filter based off of tags and then combine the results every time I make a request. Currently I'm able to filter based off of tags chosen by submitting buttons on Jinja but I'm having trouble getting it to combine when I select a new tag, when a new tag is selected it filters only using that tag and doesn't combine the dictionary from the previous result.
main.py:
#app.route('/api', methods=['GET', 'POST'])
def add_tag():
name = request.form['tags']
form = APInameForm()
url= 'https://api.hatchways.io/assessment/blog/posts?tag='+name
try:
api = requests.get(url).json()
api = api['posts']
ilist = []
nlist = []
for i in api:
ilist.append(i)
if not ilist:
output = '{<br>'
output = output + '"error": "Tags parameter is required" <br>'
output = output + '}'
return output
return render_template('/index.html', test=ilist)
except requests.ConnectionError:
return "Connection Error"
#app.route('/')
def index():
return render_template("index.html")
index.html:
{% extends 'base.html' %}
{% block content %}
<form class="text-center pt-3" method="POST" action="/api">
<input type="text" class="form-control" placeholder="Search" name="tags">
<input type="submit" value="Search" />
</form>
<br/><br/><br/>
<h1>Recommended Tags:</h1>
<form class="form-inline" method="POST" action="/api">
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="tech">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="history">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="startups">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="health">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="science">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="design">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="culture">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="history">
</input>
</div>
</form>
<br/><br/><br/>
<code>
{<br>
"posts": [{<br>
{% for item in test %}
"id": {{ item.id }}<br>
"author": {{ item.author }}<br>
"autherId": {{ item.authorId }}<br>
"likes": {{ item.likes }}<br>
"popularity" :{{ item.popularity }}<br>
"reads": {{ item.reads }}<br>
"tags": {{ item.tags }}<br><br>
{% endfor %}
}
]
</code>
{% endblock %}
I am not sure I really understand your question.
But could it be that a simple use of a set will solve your problem?
Sets can't have duplicates
https://www.w3schools.com/python/python_sets.asp
You need to store the previous data somewhere outside these functions to be able to use it in later calls to them. Temporarily, that could be in a variable defined at the top level in your module (.py file).
If you need it to persist longer (across worker threads, sessions or restarts of your custom server), you might need to write to a file or database.
To merge the JSON dictionaries you can use the dict.update method (see official docs).
Given two dict instances d1, d2, calling d1.update(d2) will merge d2 into d1, overwriting values for any keys that are the same.
combined_data = {}
#app.route('/api', methods=['GET', 'POST'])
def add_tag():
response = requests.get(url)
data = response.json()
combined_data.update(data)
# ..now render combined_data

Get value from post method to views from a for loop

I am trying to get a value from template to views.py of a django project. I am able to get the value of name="city" correctly but unable to get the exact value of name="category" in my views, instead I am getting the first element value for all the other elements in the loop. An idea to solve this will be very much helpful.
#category.html
{% for test in mytypes %}
<form id="myform" action="{% url 'my_city_category' %}" method="POST">
{% csrf_token %}
<a href="javascript: submitform()">
<div class="col-6 col-lg-3 col-md-4 col-sm-6 col-xl-2 hover-box mt-2 text-center">
<div class="pb-1 pt-2">
<img src="{{test.icon_image.url}}" width="100"/>
<h6 class="mt-3 text-body text-capitalize text-decoration-none">{{ test.category_type }}</h6>
<input type="hidden" name="category" value="{{ test.category_type }}"># unable to repeat the value while calling it in the views, stuck at the first value
<input type="hidden" name="city" value="{{ city }}"> #rendering the exact value
</div>
</div>
</a>
</form>
{% empty %}
<h6 class="mt-3 text-body text-capitalize text-decoration-none">No Categories Listed</h6>
{% endfor %}
#views.py
def City_specific_page(request):
city = request.POST.get('city')
category = request.POST.get('category')
business= Business.objects.filter(city__City=city, type__category_type=category)
return render(request, 'community_app/type_detail_city.html',{'business':business,'category':category,'city':city})
#urls.py
path('City', views.City_specific_page, name='my_city_category'),
Each <form> in your template includes the following tag:
<a href="javascript: submitform()">
I suspect that your submitform function is submitting the first form on the page, rather than the one that was clicked.
You can quickly determine if this is the problem by adding a submit button inside your <form> tags. Make sure it's not inside the <a> tags, eg:
<form id="myform" action="{% url 'my_city_category' %}" method="POST">
{% csrf_token %}
<button type="submit">Test</button>
<a href="javascript: submitform()">
<!-- the rest of your form code -->
Click the button labelled 'Test' to see if the correct form data is submitted.

Bad Request with Flask

really struggling with this bad request from flask. I know normally it caused by flask not finding the [key] in the form.. However, I've checked my form and python code 40 times and cannot see any reason that would be the case.. I have commented out each line of the python code that references request.form. I have done it 1 by 1 and I still get a bad request. However when I comment out all the lines the bad request goes away.. Any thought would be wonderful..
Python code;
if request.method == 'POST':
form = 'Add Package Form'
clientId = request.form['id']
date = request.form['date2']
strPrice = request.form['price']
price = float(strPrice)
adultlessons = request.form['adult']
juniorlessons = request.form['junior']
shortlessons = request.form['short']
playinglessons = request.form['playing']
notes = request.form['notes']
form..
<form action="/addpackage" method="post" class="sky-form">
<fieldset>
<section>
<label class="label">Select Package Date</label>
<label class="input">
<i class="icon-append fa fa-calendar"></i>
<input type="text" name="date2" id="date">
</label>
</section>
<div style="margin: -25px"></div>
<fieldset>
<section>
<label class="label">Price</label>
<label class="input">
<input type="text" name="price">
</label>
</section>
<section>
<label class="label">Adult Lessons</label>
<label class="input">
<input type="text" name="adult">
</label>
</section>
<section>
<label class="label">Junior Lessons</label>
<label class="input">
<input type="text" name="junior">
</label>
</section>
<section>
<label class="label">Short Game Lessons</label>
<label class="input">
<input type="text" name="short">
</label>
</section>
<section>
<label class="label">Playing Lessons</label>
<label class="input">
<input type="text" name="playing">
</label>
</section>
<section>
<label class="label">Notes</label>
<label class="textarea textarea-expandable">
<textarea rows="3" name="notes"></textarea>
</label>
<div class="note"><strong>Note:</strong> expands on focus.</div>
</section>
</fieldset>
</fieldset>
<!-- hidden client id -->
<input type="hidden" name="id" value="{{ client.id }}">
<!-- /hidden client id -->
<footer>
<button type="submit" name="addpackage" value="package" class="button">Add Package</button>
</footer>
</form>
This is something of a half-answer, but it was too long for a comment.
If you enable debugging in your Flask app you should get a detailed traceback indicating exactly where the problem is occurring (both in the browser and on your console).
If your application currently has something like:
app.run()
Just set the debug parameter to true:
app.run(debug=True)
If after enabling debugging you're still not sure what's causing the problem, update your question to include the traceback.
For what it's worth, if I dump your form and your code into a simple Flask app, it all seems to work just fine as long as I provide a numeric value for the price field.
Usually you'll get a 400 Bad Request in Flask while submitting a form when you try and access a form key in the request object that doesn't exist.
This is because the request.form object inherits its __getitem__ method the Multidict class in the werkzeug.datastructures module which raises a BadRequestKeyError when a key doesn't exist.
You should give the form data a default value to avoid HTTP 400 error, like this:
default_value = True
is_public = request.form.get('public', default_value)
However, I recommend you to use Flask-WTF.
With Flask-WTF, your code can be simplify to this (an example):
import ...
app = Flask(__name__)
class EditProfileForm(Form):
name = StringField('name', validators=[Length(0, 64)])
location = StringField('city', validators=[Length(0,64)])
website = StringField('website', validators=[Length(0,64), render_kw={"placeholder": "http://..."})
about_me = TextAreaField('Bio', validators=[Length(0,2000)], render_kw={"placeholder": "I'm......"})
submit = SubmitField(u'submit')
#app.route('/edit-profile', methods=['GET', 'POST'])
def edit_profile():
form = EditProfileForm()
if form.validate_on_submit():
current_user.name = form.name.data
current_user.location = form.location.data
current_user.website = form.website.data
current_user.about_me = form.about_me.data
db.session.add(current_user)
flash('Update success!', 'success')
return redirect(url_for('.user', username=current_user.username))
return render_template('edit_profile.html', form=form)
In your html file:
<form method="POST" action="/">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.location.label }} {{ form.location() }}
...
</form>
By the way, if you use Flask-Bootstrap, you can just use one line to render the whole form:
{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
I hope it will help.

Flask: Contact Page formatting with bootstrap 3

This is my first time using Flask and I have created the form for the visitors to fill out, but I want to use the bootstrap formatting so its looks similar to another form I am using in the website. Im not sure how I can link the form together. Here is my code for the contact.html page:
{% extends "index.html" %}
{% block content %}
<div class="content fixed-height">
<h3> {{ title }} </h3>
<!--<form action="http://127.0.0.1:5000/static/contact.php" method="post">
<div class="form-group">
<label>Your Name *</label>
<input type="text" name="cf_name" class="form-control" placeholder="Enter Name" required autofocus/>
</div>
<div class="controls-group">
<label class="control-label"> Your e-mail *</label>
<div class="controls">
<input type="email" name="cf_email" class="form-control" placeholder="Enter Email" required/>
</div>
</div>
<div class="form-group">
<label>Message *</label>
<textarea name="cf_message" class="form-control" placeholder="Enter Message" rows="6" required></textarea>
</div>
<input type="submit" value="Send" class="btn btn-primary">
<input type="reset" value="Clear" class="btn btn-primary">
</form> -->
<form action="{{ url_for('contact') }}" method=post
{{ form.hidden_tag() }}
{{ form.name.label }}
{{ form.name }}
{{ form.email.label }}
{{ form.email }}
{{ form.subject.label }}
{{ form.subject }}
{{ form.message.label }}
{{ form.message }}
{{ form.submit }}
</form>
</div>
{% endblock %}
The first part of the contact.html page is an old form that I was using and is in comment tags. Any help would be much appreciated
I'm guessing you're using the WTF Flask extension for working with forms?
Flask also has a Bootstrap extension that you can install using pip:
pip install flask-bootstrap
You can then import it and into the module that your Flask application instance has been created in:
from flask.ext.bootstrap import Bootstrap
app = Flask(__name__)
bootstrap = Bootstrap(app)
This will provide you with some great functionality including a helper method that you can use to quickly generate forms in your HTML templates.
Go to the page where you want to generate the form and after your extends statement do the following:
{% import "bootstrap/wtf.html" as wtf %} # imports the form template elements
# where you want your form to be
{{ wtf.quick_form(form) }} #the method takes the form argument from your view function
This will generate a form for you. You can read more about the Bootstrap extension here. Go to the Templates page and look for the section of Forms. Good luck!

django read file for importing details

I have used django-adaptops for this purpose. i have implemented the mechanism shown in docs. I need to know how can achieve this using browser , for example - i have a template where user has the option to select the csv file, once i click the import button i get the call to my view , but here i cannot read the file to upload to my model. how i can perform this.
this is my template code.
<form action="/manage/dashboard/importProspects" method="post" class="form-horizontal"
enctype="multipart/form-data"> {% csrf_token %}
<div class="row-fluid" style="margin-top: 5%">
<div class="span6">
<div class="control-group">
<p>{{ csvform.fname.label_tag }} {{ csvform.fname }} {{ csvform.fname.url }}</p>
</div>
</div>
<button type="submit" class="btn btn-small btn-success " style="margin-left:10px; ">
Import from CSV
</button>
</div>
</form>
csvForm is form object passed when this template is loaded.
the form code is below:
class ImportCsvForm(forms.Form):
fname = forms.FileField(label='CSV')
and /manage/dashboard/importProspects url will call my view importcsv which right now does not perform anything.
how can i handle this so that i can read the csv file, i cannot get the csvfile path. or am i missing some thing here ? please help.
Follow this,
in template:
<form action="/manage/dashboard/importProspects" method="post" class="form-horizontal"
enctype="multipart/form-data"> {% csrf_token %}
<div class="row-fluid" style="margin-top: 5%">
<div class="span6">
<div class="control-group">
<p>
<input type="file" name="csvfile" />
</p>
</div>
</div>
<input type="submit" class="btn btn-small btn-success " style="margin-left:10px; " />
</div>
</form>
in urls.py:
urlpatterns = patterns("mine.views",
url(r'^', 'csvupload'),)
in views.py file:
def csvupload(request):
if request.method == "POST":
f = request.FILES['csvfile']
with open("/tmp/csvfile.csv", 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
then use csvfile whatever you want.....Hope this helps to you.

Categories

Resources