Checking if item is already in database before adding it - python

I'm adding articles into a database. That worked fine, except, while the database doesn't let me create duplicates during a session, once I log out and log back in, it does. I didn't want duplicates, so I added these new lines:
maybe_existing_article = Article.query.filter_by(url=article.url)
if (maybe_existing_article):
article = maybe_existing_article.url
return "exists"
But that didn't work, I get "print("article.id=" + str(article.id))
NameError: name 'article' is not defined".
Here is the relevant code, including the new lines.
##############################################
#app.route('/bootstrap', methods=['GET', 'POST'])
def bootstrap():
posted = 1
print ("bootstrap")
global article
if request.method == 'POST':
if not request.form['title'] or not request.form['url'] or not request.form['image_url'] or not request.form['snippet']:
flash('Please enter all the fields', 'error')
else:
article = Article(request.form['title'], request.form['url'], request.form['image_url'],
request.form['snippet'])
maybe_existing_article = Article.query.filter_by(url=article.url)
if (maybe_existing_article):
article = maybe_existing_article.url
return "exists"
else:
db.session.add(article)
try:
db.session.commit()
except exc.SQLAlchemyError:
flash('Article url already exists, failed to post new article')
posted = 0
#return render_template('/error.html', article_url=article.url)
article_list = Article.query.filter_by(url=article.url)
if posted == 1:
flash('Record was successfully added')
else:
db.session.rollback()
article_list = Article.query.filter_by(url=article.url)
article=article_list[0]
print ("article.id=" + str(article.id))
import json
print("a")
return json.dumps(article.id)
else:
print("article.id=" + str(article.id))
urlNumber = str(article.id)
message = {'greeting':urlNumber}
return jsonify(message) # serialize and use JSON headers
And here's the create_tables.py:
article_table = """CREATE TABLE IF NOT EXISTS article (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
url TEXT NOT NULL,
image_url TEXT NOT NULL,
snippet TEXT NOT NULL,
date_upload TEXT DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT article_unq UNIQUE (url)
);"""

You can use an Unique constraint at the table that you want and catch the error when you try to insert a row that was already inserted. In SQLite, you can't add this constraint after the Table is created, so you would need to create the table again.
You can also add an Unique Index to the table that works almost the same:
CREATE UNIQUE INDEX index_name ON table_name(column_name);
If you can't do that, you can always send a SELECT to that table with the ID you are trying to insert and them return an error to the user if it was already inserted, although this is hardly recommended.

Related

added two search bar in django one search by id and other by name .Tried many ways but cannot do it if i try by id then i am not able to do with name

I have to make 2 search bars. I don't know how to add multiple fiels...
match= Staff.objects.filter(id=srch1...) here how can I add name=srch1
over here after trying many ways I found it but the problem is all input here is string how to change it to int
def search(request):
# Catch the data and search in Staff model.
if request.method=='POST':
srch1 = request.POST['srch']
print(type(srch1))
if type(srch1)== int:
match= Staff.objects.filter(id=srch1)
if match :
return render(request,'search.html',{'sr': match})
else:
messages.error(request,'no results,found')
elif type(srch1)== str:
catch= Staff.objects.filter(name=srch1)
if catch:
return render(request,'search.html',{'sr': catch})
else:
messages.error(request,'no results,found')
else:
return HttpResponseRedirect("/search")
return render(request,"search.html")
You should be using a GET request with querysting parameters or (url parameters, which is a bit more complicated) for this, not a POST. Here's how I would do this:
def search(request, *args, **kwargs):
# Initial empty query dictionary for use with query later.
query = {}
# Getting 'name' and 'id' from querystring parameters (i.e. ?id=1&name=foo)
name = request.GET.get('name', None)
id = request.GET.get('id', None)
# Add 'id' to the query dictionary if it exists
if id is not None:
query['id'] = id
# Add name to the query dictionary if it exists
if name is not None:
query['name'] = name
# If the query dictionary has name or id, get the Staff entry from the database
if query.get('name', None) or query.get('id', None):
# Note that .filter() returns a QuerySet. You should probably use .get()
# since my guess is that you only want one Staff object (judging by your
# search parameters). Also note that since we are using **query we will be
# using BOTH 'name' AND 'id' to search for the Staff, as long as both exist in
# the query dictionary.
match = Staff.objects.get(**query)
# If there is a match, send it in the rendered response context dict
if match:
return render(request, 'search.html', {'sr': match})
# no match, send message notifying that a Staff entry was not found matching
# the desired criteria
return render(request, 'search.html', {message: 'Not Found'}
# There were no query parameters, so we are not searching for anything.
else:
return render(request, 'search.html')
You can see that the above code is much simpler, and more concise. This will help you or anyone else checking out your code in the future to better understand what you're trying to acheive.
P.S. I typically only use POST requests when I am creating an entry in the database. Maybe this is preference, but to my knowledge it is best practice to use a GET request for search.

How to get query in sqlalchemyORM также

I have few form fields on search page. After performing the search, my page should display a list of possible matching results. If the user typed in only part of a title, ISBN, or author name, search page should find matches for those as well. Also if user typed only one or few field - page should show all matches.
Idk how to write query. If i have one value from request.form and other values is None - so whole query is empty
#app.route('/search', methods=("GET", "POST"))
def search_book():
books = None
if request.method == "POST":
isbn = request.form['isbn']
title = request.form['title']
author = request.form['author']
year = request.form['year']
books = db.query(Books).filter_by(isbn=isbn, title=title, author=author, year=year).all()
return render_template("search.html", books=books)
.filter_by(multiple arguments) will default to AND, meaning the user will have to enter data that matches all fields
This also means that if the user leaves fields empty, the query will only return books that have (for example) title = " " (when title form is empty), despite having entered a valid year.
This is probably not intended, from a user point of view. A way to fix this is to (1. validate input data, and then) add filters to a list if they are not empty, then add the non-empty fields using or_(*filter_list). Query will then return all rows that match any field specified by the forms.
from sqlalchemy import or_
query = db.query(Books)
filter_list = []
if request.form['isbn']:
filter_list.append(Book.isbn.ilike(request.form['isbn']))
if request.form['author']:
filter_list.append(Book.author.ilike(request.form['author']))
# etc...
if len(filter_list) > 0:
query = query.filter(or_(*filter_list))
didnt test code but *filter_list allows you to pass a list to the filter method, or_ allows you to change the default AND to OR
more here:
Using OR in SQLAlchemy
Use the 'or_()' method . This will search all the matching results for any given column
name = request.form.get('res')
result = Books.query.filter(db.or_(Books.author==name , Books.isbn==name , Books.title==name)).all()
'res' is the search entry given by the user in the search form in your html page , as mentioned it can be anything ISBN , title or the author's name

Syntax error at the end of input when executing psycopg2

I am trying to add a COLUMN to certain table using psycopg2, from a Django function to a table in PostgreSQL. The name of the column is define in the views.py file of the Django project.
I have been trying with a some similar questions in stack over flow but none have worked for me.
View:
def parameter_creation(request):
if request.method == 'POST':
name = request.POST['name']
min_value = request.POST['min_value']
max_value = request.POST['max_valu']
if ParameterModel.objects.filter(name=unidecode(name.upper())).exists():
return JsonResponse('name', safe = False)
else:
form = New_Parameter_Form(request.POST)
if form.is_valid():
info = form.save(commit = False)
info.name = unidecode(name.upper())
data_analysis.column_aggregation(name)
data_analysis function:
def column_aggregation(name_column):
cursor.execute("""ALTER TABLE simulated_data ADD COLUMN %s""" %
name_column)
cursor.commit()
Once the code is executed, the output is the next error:
cursor.execute("""ALTER TABLE simulated_data ADD COLUMN %s""" %
name_column)
psycopg2.errors.SyntaxError: syntax error at end of input
LINE 1: ALTER TABLE simulated_data ADD COLUMN Eng_temp

Python/Django/Q search, How to find B field info. by searching A field info

Most examples are in the form of finding A in data A to Z.
A DB table does not have a single field from A to Z. When a DB table has several fields together, I want to know the field I'm looking for as a field value and I want to figure out another value with that field value.
For example, searching for a specific name in a DB that contains information from all the students will determine the age.
from Python, Django DB
My data consists of 3 rows:
{title:'1', price:'20'}
{title:'2', price:'30'}
{title:'1', price:'10'}
I want to find title '1' and then return price fileds
Expexted Output:
{title:'1', price:'20'}
{title:'1', price:'10'}
Views.py:
#csrf_exempt
def searching(request):
if request.method == "POST":
parameter = request.POST.get('title')
searchResult = NaverData.objects.filter(Q(title__icontains=parameter)).distinct()
ouput = searchResult
return HttpResponse(ouput)
else:
#GET request
return HttpResponse('GET REQUEST')
Try below code:
searchResult = NaverData.objects.all().filter(title=parameter)
check this
searchresult= NaverData.objects.values("prize").filter(title__exact=parameter)

How to fix a KeyError in django?

print user_dic[id] displays the right result PersonA. This is when I input the id manually.
user_stream = {u'2331449': u'PersonB', u'17800013': u'PersonA'}
user_dic= {}
for item in user_stream:
user_dic[item['id']] = item['name']
id = '17800013'
print user_dic[id] #returns the right value
However, when I try to put the user_id through a for loop that iterates through json I get an error: KeyError at 17800013 for the line name = user_dic[user_id]. I don't understand why the user_dic[id] works when manually inputting the id, but user_dic[user_id] doesn't work when going through the for loop even though the input is the same.
#right fql query
fql_query = "SELECT created_time, post_id, actor_id, type, updated_time, attachment FROM stream WHERE post_id in (select post_id from stream where ('video') in attachment AND source_id IN ( SELECT uid2 FROM friend WHERE uid1=me()) limit 100)"
fql_var = "https://api.facebook.com/method/fql.query?access_token=" + token['access_token'] + "&query=" + fql_query + "&format=json"
data = urllib.urlopen(fql_var)
fb_stream = json.loads(data.read())
fb_feed = []
for post in fb_stream:
user_id = post["actor_id"]
name = user_dic[user_id] #this is the line giving me trouble
title = post["attachment"]["name"]
link = post["attachment"]["href"]
video_id = link[link.find('v=')+2 : link.find('v=')+13]
fb_feed.append([user_id, name, title, video_id])
There is no need for user_dic. What you are doing in first part is just a redundant work and you are also doing it wrong. Your user_stream is already in a form how you wanted it. Your first part should contain this line:
user_stream = {u'2331449': u'PersonB', u'17800013': u'PersonA'}
And in second part (at line where you are facing problem) you should do:
name = user_stream[user_id]
If you think that you will face KeyError then dict has a method .get, which returns None if the Key is not found. You can specify your value instead of None to return if there is KeyError
name = user_stream.get('user_id')
#returns None by default
name = user_stream.get('user_id', '')
#returns empty string now
#on both cases exception will not raised

Categories

Resources