I am trying to create a search page where buttons can be clicked which will filter the posts like in this page [Splice Sounds][2] (i think you need an account to view this so ill add screenshots).
To do this i think i need to pass a list so that i can filter by that list but i can't find a way to do this.
having a GET form for each genre (which is being created by a for loop) would allow me to filter by one genre at a time but i want to filter by multple genres at once so that won't work
in the site that i linked to: they pass the genres/tags into the url so how could i do this in django?
Also: i could make seperate url paths and link to those but then i would have to do this for every combination of genres/tags which would be too much so i can't do that.
the link shows a site which passes tags through url like this https://splice.com/sounds/search?sound_type=sample&tag=drums,kicks
here is some relevant code:
this is how i want to filter which is why i need to pass a list of args
for arg in args:
Posts = Posts.filter(genres=arg)
urls
urlpatterns = [
path('', views.find, name='find'),
path('searchgenres=<genres_selected>', views.find_search, name='find_search'),
]
EDIT: I have tried this many ways such as using ajax but i couldn't get that to work well
EDIT 2: i have changed the question to How To Pass Only Selected Arguments Through URL
To pass a list into a request you could:
Use html checkboxes and in views aggregate them into a list
Use a single textbox and parse in views
If you obtain the request as a list, you could use Post.objects.filter(genre__in=genres).
It might also be helpful to know that Django allows for complex lookups with Q objects from django.db.models import Q. The | character represents OR. This allows complex filtering. For instance:
Posts.objects.filter(Q(genre='Pop') | Q(genre='Rock') | Q(genre='Jazz'))
I have a Flask application and need to store users' place when they navigate the content.
For example, I have a route like this: #main_bp.route('/articles/<category>/<article_number>', defaults={'category': 'new'})
The content is organized such that you page through articles under a category: starting at 0, then 1, and so forth. The URL for article number 3 would look like: articles/<category>/3
I'd like to save users' place so that if they leave the site after visiting article 3, when they navigate to the articles page they'll land on articles/<category>/3, rather than articles/<category>/0.
What is the best way to achieve this? Currently, I've modeled the data in the database so there is a column that looks like category_article_last_visited (integer). I'm able to store this data as a user browses the site, but I'm not sure how to retrieve it when they return to the articles page.
What I've tried:
#main_bp.route('/articles/<category>/<article_number>', defaults={'category': 'new', 'article_number':current_user.category_article_last_visited}), but I get an error that there is no such attribute.
Checking current_user.category_article_last_visited in the routes function and using the article number. This renders the correct content, but doesn't change the URL, which won't work.
Redirecting users if they have a value for current_user.category_article_last_visited. This doesn't seem to yield any change.
I am curious if storing in the db (assigning the value, db.commit(), etc.) is the right path, or if I should explore flask-sessions more. I need this information to persist across sessions, so that if a user logs out, clears cookies, uses a different device, etc. it is still available. I may also perform analytics on these values in the future.
Is the method I've described above the best way to achieve this? Is flask-sessions or something else preferable?
If the method outlined above is best, how do I correctly route this information so that users are directed to the page they left off, and the URL is changed appropriately?
Thanks
I would go with the redirect solution, it is more clear.
I would add an if statement at the beginning of the route-function and if there is data for this user, i would redirect to that page. For example:
#main_bp.route('/articles/<category>/<article_number>', defaults={'category': 'new'})
def routefunc():
if current_user.category_article_last_visited !=0: #or whatever your column keeps for empty data
return redirect ('/articles/'+yourcategory +'/'+ current_user.category_article_last_visited #as string
This must be combined with some other functionality, to avoid infinitive redirection to this route:
Option 1:
You can add another variable in the route that will have specific value on these redirections and will ignore this if statement. For example:
#main_bp.route('/articles/<category>/<article_number>/<check>', defaults={'category': 'new'})
def routefunc():
if current_user.category_article_last_visited !=0 and check!=1: return redirect ('/articles/'+yourcategory +'/'+ current_user.category_article_last_visited+'/1')
However in this case you must add this variable (with some other value different from 1) to all of your urls-hrefs etc and it will make your urls more "dirty". It would be effective for a small app, but i would avoid it for a big app/website with multiple internal links.
Option 2:
You could add one more column in your database table that will be 1/0 depending on when user visitis this route, directly or from redirection. In this case you must add a couple of queries to check and/or update this value before-after redirection.
Option 3:
You could create another similar route that will only handle redirections, and produce the same results (same html) but without the if statement. For example:
#main_bp.route('/articles/<category>/<article_number>', defaults={'category': 'new'})
def routefunc():
if current_user.category_article_last_visited !=0: #or whatever your column keeps for empty data
return redirect ('/articles2/'+yourcategory +'/'+ current_user.category_article_last_visited #as string
#main_bp.route2('/articles2/<category>/<article_number>', defaults={'category': 'new'})
def routefunc():
return ('yourhtml.html')
***Session based approach is not good here, as you want a long term solution.
As you probably have many categories, articles, users, you would better create a separate table specifically for this
I don't know what is the best way to achieve what you want but here's what you could try. Assuming you want to perform some analytics on the data you might want to store it in a database.
You could have a route designed to create a user cookie when a new user visits your page and redirects him to the articles page with the new cookie set:
#main_bp.route('/articles/set_cookie', "GET"])
def set_article_cookie():
sessionserializer = securecookiesessioninterface().get_signing_serializer(main_bp)
tempcookie = sessionserializer.dumps(dict(session))
resp = make_response(redirect('/articles'))
resp.set_cookie("user", tempcookie)
return resp
And your existing route in which you check if the user has already visited the page. In which case you will want to check in the database what was the last article he read and redirect him accordingly:
#main_bp.route('/articles/<category>/<article_number>', defaults={'category': 'new'})
def articles(category, article_number):
# If the user cookie is already set, check if there is some data is the database and redirect to his last article visited
cookie = request.cookies
if "user" in cookie:
# Retreive the user cookie value and check the database for this value
return redirect('/articles/' + last_article_visited)
# Else redirect the user to set_article_cookie
else:
return redirect("/set_article_cookie")
OK, here is the solution I decided on:
I update the paths of nav links throughout the site, so instead of /articles/<category>/0 it's /articles/<category>/current_user.article_number_last_visited
Since not all users have visited articles in every category, I added default routing logic, similar to:
#main_bp.route('/articles/<category>/', defaults={'article_number': 0})
#main_bp.route('/articles/<category>/<article_number>', methods=['GET', 'POST'])
This routes users correctly even if current_user.article_number is null.
I believe this will also work if the user is not logged in (and therefore there will be no article_number attribute). I haven't checked this case out thoroughly though because in my use case users have to be logged in to view content.
I'm trying to log in a user and print all the latest 10 articles along with the number of comments and number of votes.
My views.py for that function goes like this:
article_query=Article.objects.filter(creator=user.id)
article = Article.objects.all()
latest_articles = article.order_by('-pub_date')
return render_to_response('home.html', {'article_user': article_query, 'user_info':user_info, 'latest_articles':latest_articles}, RequestContext(request))
However, I don't have a dedicated section as vote_count or comment_count stored in the database. I'm just storing the ids of the users that may have voted or commented separated by a semicolon (;)in a text field. Eg. votes--> (2;4;6;)
How can I output the number of votes in the template? Should I have to make a dedicated cell as votes_count in the database or should I achieve this by coding some cumbersome function in the views file and then displaying it? Which is the conventional method for websites having millions of users?
I'm trying to use whoosh to add search functionality to my blogapp on appengine but I don't understand some stuff.
The blogentries are indexed with title, content and status fields.
I would like to have different type of results on the public page then on the admin page but without the need to have multiple indexes.
On the frontpage I want visitors to be able to search on visible entries only on the title and content fields and in the admin I want to search also on draft entries.
Can i concatenate searches using QueryParser so I can search on multiple fields?
How could I filter on status:visible with MultifieldParser?
EDIT
didn't test it yet but i got an answer on the whoosh mailing list:
# Create a parser that will search in title and content
qp = qparser.MultifieldParser(["title", "content"], ix.schema)
# Parse the user query
q = qp.parse(user_query_string)
# If request is not admin, filter on status:visible
filterq = query.Term("status", u"visible") if not is_admin else None
# Get search results
results = searcher.search(q, filter=filterq)
I know this is not strictly an answer but Google added a full text search api similar to whoosh. Perhaps you should try it.
https://developers.google.com/appengine/docs/python/search/overview
I'm trying to parse an html form using mechanize. The form itself has an arbitrary number of hidden fields and the field names and id's are randomly generated so I have no obvious way to directly select them. Clearly using a name or id is out, and due to the random number of hidden fields I cannot select them based on the sequence number since this always changes too.
However there are always two TextControl fields right after each other, and then below that is a TextareaControl. These are the 3 fields I need access too, basically I need to parse their names and all is well. I've been looking through the mechanize documentation for the past couple hours and haven't come up with anything that seems to be able to do this, however simple it should seem to be (to me anyway).
I have come up with an alternate solution that involves making a list of the form controls, iterating through it to find the controls that contain the string 'Text' returning a new list of those, and then finally stripping out the name using a regular expression. While this works it seems unnecessary and I'm wondering if there's a more elegant solution. Thanks guys.
edit: Here's what I'm currently doing to extract that info if anyone's curious. I think I'm probably just going to stick with this. It seems unnecessary but it gets the job done and it's nothing intensive so I'm not worried about efficiency or anything.
def formtextFieldParse(browser):
'''Expects a mechanize.Browser object with a form already selected. Parses
through the fields returning a tuple of the name of those fields. There
SHOULD only be 3 fields. 2 text followed by 1 textarea corresponding to
Posting Title, Specific Location, and Posting Description'''
import re
pattern = '\(.*\)'
fields = str(browser).split('\n')
textfields = []
for field in fields:
if 'Text' in field: textfields.append(field)
titleFieldName = re.findall(pattern, textfields[0])[0][1:-2]
locationFieldName = re.findall(pattern, textfields[1])[0][1:-2]
descriptionFieldName = re.findall(pattern, textfields[2])[0][1:-2]
I don't think mechanize has the exact functionality you require; could you use mechanize to get the HTML page, then parse the latter for example with BeautifulSoup?