Flask Python pass data on link click - python

I am working on a recipes database. My issue is with showing the result of a search. I can search the database by ingredient and get a list of recipes with that ingredient. I display those results on a new page; I show just the title of the recipe and I make it a link to a 'showrecipe' page. But I cannot find a way to send the recipe id to the new page so it knows which recipe to show. Here are the relevant bits of code so far:
The Search Form:
class SearchIngredientsForm(FlaskForm):
ingredients_string = StringField('ingredients_string', validators=[InputRequired(), Length(min=1)])
# search_string = StringField('Search string', [InputRequired()])
submit = SubmitField('Search')
and the search route:
#app.route('/search', methods=['GET','POST'])
def search():
form = SearchIngredientsForm()
if form.validate_on_submit():
search_ingredients_string = form.ingredients_string
search_ingredients_list = search_ingredients_string.data.split(',')
recipe_ids = []
ingredient_objects = []
if search_ingredients_list:
for ingredient_name in search_ingredients_list:
ingredient_objects.extend( Ingredient.query.filter(Ingredient.line.like(f'%{ingredient_name}%')).all() )
if ingredient_objects:
for ingredient in ingredient_objects:
recipe_ids.append(ingredient.recipe_id)
session['recipe_ids'] = recipe_ids
return redirect(url_for('results'))
return render_template('search.html', form=form)
and the results.html
{% extends 'layout.html' %}
{% block content %}
<h1>Results</h1>
{% for result in recipe_objects %}
{{ result.title }} which serves: {{ result.serves }}
{% endfor %}
{% endblock content %}
and finally the showrecipe route. I cannot seem to get the id to pass through.
#app.route('/showrecipe/<id>', methods=['POST', 'GET'])
def showrecipe(id):
recipe = Recipe.query.get(id)
return render_template('showrecipe.html', recipe=recipe)
When I click on the recipe title on the results page I get a 'url not found' error.
Thanks in advance for any help.
Update
Here is the results route:
#app.route('/results')
def results():
recipe_ids = session.get('recipe_ids')
recipe_objects = []
if recipe_ids:
for recipe_id in recipe_ids:
recipe_objects.append(Recipe.query.get(recipe_id))
return render_template('results.html', recipe_objects=recipe_objects)

Related

HTML shows Flask-SQLAlchemy syntax?

When trying to display replies of users on my page it displays them with SQL syntax, like so: ('reply',) I've tried str() when returning from my route.
html:
<ul style="float:left;" class="list-group list-group-flush" id="anons">
{% for reply in replies %}
<li class="list-group-item" align="left">
{{ reply }}
</li>
{% endfor %}
model:
class Reply(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30))
data = db.Column(db.String(10000))
date = db.Column(db.DateTime(timezone=True), default=func.now())
route:
#views.route('/', methods=["GET", "POST"])
def home():
if request.method == "POST":
name = request.form.get("name")
data = request.form.get("reply")
if len(data) >= 1:
new_reply = Reply(name=name, data=data)
db.session.add(new_reply)
db.session.commit()
replies = db.session.query(Reply.data)
return render_template('home.html', replies=replies)
return render_template('home.html')
Try modifying your replies definition to this:
replies = Reply.query.all()
This essentially creates a list of all the 'Reply' objects, which you then pass to the template. If you were wanting to only show the .data attribute of each 'Reply', you would access that with {{ reply.data }} in the for loop.

Data rendering in django

Each user has certain vacations that he adds. I want to render his vacations and not anyone else's. What should I do?
The view below shows all vacations, but I only want to show the vacations of a particular user.
def all_vacations(request):
vacations = Vacation.objects.all()
return render(request, 'homePage.html', {'vacations': vacations})
You have to do something like this:
Your URLs:
path('users', views.users_view, name='users')
path('vacation/<int:pk>/', views.user_vacations, name='user_vacation')
Create a view:
# You have to create a view to list users
# List your users
def users_view(request):
users = User.objects.all()
return render(request, 'your_template.html', {'users': users})
Create a template to list users:
<!--In your template:-->
{% for user in users %}
<ul>
<li>{{ user}}</li>
<ul>
{% empty %}
<!-- Do something -->
{% endfor %}
Lastly, you return what you want:
def user_vacations(request, id):
vacations = Vacation.objects.get(author__id=id)
return render(request, 'homepage.html', {'vacations': vacations})

How to add parameters in a url in render method - Django?

How to add parameters in a url in render method - Django?
I'm having difficulty adding pagination to a search result.
On the first page the result is shown perfectly, but from the second page onwards, the search parameter no longer exists.
thank you.
def get(self, request):
clientes = Cliente.objects.filter(
Q(nome__icontains=request.GET['nome']))
formPesquisa = FormPesquisaCliente()
paginator = Paginator(clientes, 40)
page = request.GET.get('page')
clientes = paginator.get_page(page)
response = render(request, 'cliente/index.html', {
'clientes': clientes,
'formPesquisa': formPesquisa})
response['Location'] += '?nome=' +request.GET['nome']
return response
What are you missing is that when you have filtered data from the queryset and its paginated so obviously to view the next page you need to maintain the state by passing the same filter object nome. So the url should look something like this.
http://localhost:8000/clients/?page=2&nome=something
def get(self, request):
abc = request.GET.get['nome']) #<--- variable to get value from view
clientes = Cliente.objects.filter(
Q(nome__icontains=abc)) #<-- pass the abc variable here
formPesquisa = FormPesquisaCliente()
paginator = Paginator(clientes, 40)
page = request.GET.get('page')
clientes = paginator.get_page(page)
response = render(request, 'cliente/index.html', {
'clientes': clientes,
'formPesquisa': formPesquisa,
'abc':abc}) #<-- passing the abc variable to view to maintain the state of your filter.
response['Location'] += '?nome=' +request.GET['nome']
return response
Example Pagination Code:
<div class="pagination">
<span class="step-links">
{% if clients.has_previous %}
« first
{% if nome %}
previous
{% else %}
previous
{% endif %}
{% endif %}
<span class="current">
Page {{ clientes.number }} of {{ clientes.paginator.num_pages }}.
</span>
{% if clientes.has_next %}
{% if nome %}
next
last »
{% else %}
next
last »
{% endif %}
{% endif %}
</span>
</div>

SelectMultipleField default value is not being selected on HTML

c.ingredientsI am creating a Flask sample app for learning purposes and I have a Form called CocktailForm that contains a SelectMultipleField. This form should be used for creating new cocktails objects as well as for updating them:
class CocktailForm(Form):
name = StringField('What is the coktail\'s name?', validators=[Required()])
ingredients = SelectMultipleField('Ingredients',
coerce=int,
)
submit = SubmitField('Submit')
For editing I want to load the same form with the cocktail data. It works for name, and for loading all choices but I also want to select those choices that are ingredients of that cocktail:
#main.route('/edit/<int:id>', methods=['GET', 'POST'])
def edit(id):
try:
c = Cocktail.query.filter(Cocktail.id == id).one()
form = CocktailForm()
form.ingredients.choices = [(i.id, i.name) for i in Ingredient.query.all()]
if form.validate_on_submit():
c.name = form.name.data
cocktail_ingredients = Ingredient.query.filter(Ingredient.id.in_(form.ingredients.data)).all()
c.ingredients.extend(cocktail_ingredients)
db.session.commit()
else:
form.name.data = c.name
form.ingredients.default = [(i.id, i.name) for i in c.ingredients]
return render_template('new.html', form=form)
except Exception, e:
print e
return redirect(url_for('.index'))
I get unexpected results since on the HTML those choices are not displayed but when I submit the form it seems like those choices are always selected even if you select a new ones.
The template is quite simple:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Cocktails{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>New Cocktail</h1>
{{ wtf.quick_form(form) }}
</div>
{% endblock %}
This is what you can see in in the browser. I am editing Gintonic cocktail which is composed of gin and tonic. However they are not displayed as selected:
Browser
Thanks in advance, any tip will be appreciated
The line form.ingredients.default = [(i.id, i.name) for i in Ingredient.query.all()] does not set the selected values. You want to change it to be form.ingredients.data = [i.id for i in c.ingredients].
You should have a redirect/render_template in the validate block, but that is optional.

django 1.5: not being able to get the values of variable in view

I am new to django. I have django 1.5. I want to take two variables from one template to some other template. but i am not receiving the value instead just nothing received.
Code of the Template from which i want to send variable as a part of url is:
<div class="tags">
{% for tags1 in document.tags.all %}
{% if tags1.name|length > 0 %}
{% with tags1.name as tagts %}{% endwith %}
{{ tags1.name }}
{% endif %}
{% endfor %}
</div>
Code of the URL where i am calling Second View is:
url(r'^tag_related/(?P<username>[-\w\.#]+)/(?P<tagts>)/$',
tag_related_document,
{'template_name': 'document/tag_related_document.html'},
name = 'tag_related_document'
),
Code of the View tag_related_document is:
def tag_related_document(request, username, tagts, template_name , page_template="userprofile/entry_index_page.html"):
"""
documents Related to tag """
try:
notifications = request.user.notifications.all()[:100]
except AttributeError:
notifications = ""
user = get_object_or_404(User, username = username)
try:
user_profile = user.get_profile()
except UserProfile.DoesNotExist:
messages.error(request, "Profile does not exist.")
return HttpResponseRedirect(reverse('homepage'))
documents = Document.objects.filter( Q(tags__in = user_profile.tags.all()) , date_deleted = None).order_by("-date_added")
if not documents:
documents = Document.objects.filter( date_deleted = None).order_by("?")
related_doc_widget = Document.objects.filter( Q(tags__in = user_profile.tags.all()) , date_deleted = None).order_by('?')
if not related_doc_widget:
related_doc_widget = Document.objects.filter( date_deleted = None).order_by("?")
followers_widget = Felloz.objects.get_followers(user = user_profile.user)
followings_widget = Felloz.objects.get_followings(user = user_profile.user)
# recommendations_widget = UserProfile.objects.filter(Q(~Q(user__in = followings_widget) or ~Q(user = request.user) ) ).order_by('?')
recommendations_widget = UserProfile.objects.filter( tags__in = user_profile.tags.all() ).distinct().exclude(user__in = followings_widget).exclude( user = user )
if not recommendations_widget:
recommendations_widget = UserProfile.objects.filter(~Q( user__in = followings_widget ) ).exclude( user = user ).order_by('?')
ideas_widget = Idea.objects.filter(user = user).order_by('?')
for idea in ideas_widget:
is_substring = "<a" in idea.idea_html
if(is_substring is False):
idea.idea_html = truncate_chars(idea.idea_html,50)
else:
idea.idea_html = htmltruncate.truncate(idea.idea_html,50,ellipsis='')
no_of_documents = len( Document.objects.filter(author = user) )
no_of_ideas = len(Idea.objects.filter(user=user))
try:
slug_status = SlugStatus.objects.get(user=user)
except SlugStatus.DoesNotExist:
slug_status = ''
context = {
'slug_status':slug_status,
'documents': documents,
'page_template': page_template,
'followers_widget': followers_widget,
'followings_widget': followings_widget,
'related_doc_widget': related_doc_widget,
'user': user,
'site': Site.objects.get_current(),
'profile':user_profile,
'recommendations_widget': recommendations_widget,
'no_of_documents':no_of_documents,
'no_of_ideas': no_of_ideas,
'notifications': notifications,
'notifications_unread': request.user.notifications.unread(),
'idea_widget': ideas_widget,
'tagts':tagts,
}
print '=============i m here==================='
print tagts
print '=============i m here==================='
#related_doc_widget = Document.objects.filter(~Q(author = user) and ~Q(tags__in = UserProfile.tags.all())).order_by('?')
#recommendations_widget = UserProfile.objects.filter(~Q(user__in = followings_widget) and ~Q(user = user)).order_by('?')
#documents_newsfeed = Document.objects.filter(Q(author = user) | Q(author__in = followings_widget), date_deleted = None).order_by("-date_added")
if request.is_ajax():
template_name = page_template
return render_to_response(template_name, context, context_instance=RequestContext(request))
return render_to_response(template_name, context, context_instance=RequestContext(request))
The code of the Second Template where i want to show that variable is:
{% if profile.user == request.user %}
<h2 class="mainHeading"> Documents Related To: {{tagts}} </h2>
{% else %}
<h2 class="mainHeading"> Documents Related To: {{tagts}}</h2>
{% endif %}
But i am getting here nothing.... Please help thanks in advance....
You are closing {% with %} before {% url %} so url is being based on empty value, i think it's the reason.
And please, in future avoid posting large pieces of irrelevant code. Shrink it down to minimal amount which is needed to reproduce error.
Should be like this unless the code doesn't resemble the one you posted.
{% for tags1 in document.tags.all %}
{% if tags1.name|length > 0 %}
{% with tags1.name as tagts %}
{{ tags1.name }}
{% endwith %}
{% endif %}
{% endfor %}

Categories

Resources