How to pass variable from view function to jinja2 template - Flask app - python

I'm writing a basic messaging function inside my app and it does what it's suppose to do. It sends, receives and sort messages in inbox and outbox, and I wanted it to show the nicknames of those who send (TO: 'nickname') and those who receive the message (FROM: 'nickname')
SOLVED
class Message(db.Model):
id = db.Column(db.Integer, primary_key = True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime)
for_id = db.Column(db.Integer)
**for_nickname = db.Column(db.String(140))**
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self): # pragma: no cover
return '<Message %r>' % (self.body)
I just added one more field in my table for the nickname, so I can access it from the posted data. I felt that writing 2 more queries and comparing them to get this same result is too much for something like this.
Edited:
the view:
#app.route('/poraki', methods = ['GET', 'POST'])
#login_required
def poraki(page=1):
form = PostMessage()
nick = form.nickname.data
nickname = User.query.filter_by(nickname = nick).first()
if form.validate_on_submit():
m = Message(body = form.post.data,
timestamp = datetime.utcnow(),
author = g.user,
for_id = nickname.id)
db.session.add(m)
db.session.commit()
flash(gettext(u'Вашата порака е пратена!'))
return redirect(url_for('poraki'))
#inbox
sent = User.query.filter_by(nickname = g.user.nickname).first()
all_inbox = Message.query.filter_by(for_id = sent.id).order_by(Message.timestamp.desc()).paginate(page, POSTS_PER_PAGE, False)
#sent
all_sent = Message.query.filter_by(user_id = sent.id).order_by(Message.timestamp.desc()).paginate(page, POSTS_PER_PAGE, False)
return render_template('messages.html', form = form, posts1 = all_sent, posts2 = all_inbox, title = u'Пораки')
PostMessage():
class PostMessage(Form):
nickname = TextField('nickname', validators = [Required()])
post = TextField('post', validators = [Required()])
message.html template:
<td width="70px"><img src="{{post.author.avatar(70)}}" /></td>
<td>
{% autoescape false %}
{% if prateni == 1 %}
<p>{{ _('До: %(nickname)s ', nickname = '%s' % (url_for('user', nickname = post.for_id), post.for_id)) }}</p>
{% else %}
<p>{{ _('Од: %(nickname)s ', nickname = '%s' % (url_for('user', nickname = post.author.nickname), post.author.nickname)) }}</p>
{% endif %}
{% endautoescape %}
<p><strong><span id="post{{post.id}}">{{post.body}}</span></strong></p>
{% autoescape false %}
<p>{{ _('%(when)s', when = momentjs(post.timestamp).fromNow() ) }} </p>
{% endautoescape %}
<!-- {% if post.author.id == g.user.id %}
<div>{{ _('Избриши') }}</div>
{% endif %} -->
</td>
messages.html template:
<div class="well">
<form class="form-horizontal" action="" method="post" name="post">
{{form.hidden_tag()}}
<div class="control-group{% if form.errors.post %} error{% endif %}">
<label class="control-label" for="nickname">{{ _('До:') }}</label>
<div class="controls">
{{ form.nickname(size = 30, maxlength = 140) }}
{% for error in form.errors.nickname %}
<span class="help-inline">[{{error}}]</span><br>
{% endfor %}
</div>
</div>
<div class="control-group{% if form.errors.post %} error{% endif %}">
<label class="control-label" for="post">{{ _('Порака:') }}</label>
<div class="controls">
{{ form.post(cols = 64, rows = 4, class = "span4") }}
{% for error in form.errors.post %}
<span class="help-inline">[{{error}}]</span><br>
{% endfor %}
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn btn-primary" type="submit" value="{{ _('Прати!') }}">
</div>
</div>
</form>
</div>
<table class="table">
<tr>
<td width=50%> Пратени пораки {{ proba }}
{% set prateni = 1 %}
{% for post in posts1.items %}
{% include 'message.html' %}
{% endfor %}
</td width=50%>
<td> Примени пораки
{% set prateni = 0 %}
{% for post in posts2.items %}
{% include 'message.html' %}
{% endfor %}
</td>
</tr>
</table>

Related

How to display multiple items under 1 category name?

views.py :
def gerechten(request):
template = loader.get_template('café/gerechten.html')
mydata = gerecht_info.objects.all()
mydata2 = gerechten_Categorie.objects.all()
context = {
'mygerecht': mydata,
'mycategories': mydata2
}
return HttpResponse(template.render(context, request))
models.py :
class gerechten_Categorie(models.Model):
categorie = models.CharField(max_length=200)
def __str__(self):
return self.categorie
class gerecht_info(models.Model):
categorie = models.ForeignKey(gerechten_Categorie, on_delete=models.CASCADE)
gerecht_name = models.CharField(max_length=200)
gerecht_description = models.CharField(max_length=500, blank=True, null=True)
gerecht_price = models.CharField(max_length=50)
def __str__(self):
return self.gerecht_name
def drinkdesc(self):
return self.gerecht_description
def drinkprice(self):
return self.gerecht_price
gerechten.html :
{% if mygerecht %}
{% for cat in mygerecht %}
<div class="flex">
<div class="menu-head center">
<h2>{{cat.categorie}}</h2>
</div>
<div class="menu-item">
<ul class="price">
<li>{{cat.gerecht_name}}</li>
<li>€{{cat.gerecht_price}}</li>
</ul>
{% if cat.gerecht_description %}
<p>{{cat.gerecht_description}}</p>
{% else %}
<p></p>
{% endif %}
</div>
</div>
{% endfor %}
{% else %}
<div class="menu-head center">
<h2>no items avaible</h2>
</div>
{% endif %}
Looks like this but I want all info from 'Hapjes' into 1 'Hapjes' category, not separated.
I think what you are trying to achieve can be done with regroup template tag.
{% regroup mygerecht by categorie as article_categories %}
{% for categorie in article_categories %}
<div class="flex">
<div class="menu-head center">
<h2>{{categorie.grouper}}</h2>
</div>
{% for article in categorie.list %}
<div class="menu-item">
<ul class="price">
<li>{{article.gerecht_name}}</li>
<li>€{{article.gerecht_price}}</li>
</ul>
<p>{% if article.gerecht_description %}{{article.gerecht_description}}{% endif %}</p>
</div>
{% endfor %}
</div>
{% endfor %}

Flask list of fields gets the data inside just the first element

I am trying to get the data from a form that is made dynamically using Flask and WTForms. To do that I've created a list that gets populated when a user opens the link, but when I try to get the data from html I only get the data from the first element of the list.
Forms:
class Details_Form(FlaskForm):
preschool_groups = []
classes = []
continue_button = SubmitField('Continuă')
def appeend_group(self):
preschool_details = Preschool_Details()
self.preschool_groups.append(preschool_details)
def appeend_class(self, choices):
class_details = Classes_Details()
class_details.class_type.choices = choices
self.classes.append(class_details)
class Preschool_Details(FlaskForm):
group_name = StringField('', validators=[DataRequired()])
group_size = IntegerField('', validators=[DataRequired()])
class Classes_Details(FlaskForm):
class_name = StringField('', validators=[DataRequired()])
class_size = IntegerField('', validators=[DataRequired()])
class_type = SelectField('', validators=[DataRequired()])
Routes:
#app.route('/detalii-scoala/<school>/<groups>/<classes>', methods=['GET','POST'])
#login_required
def school_details_page(school, groups, classes):
groups = int(groups)
classes = int(classes)
details_form = Details_Form()
details_form.classes.clear()
details_form.preschool_groups.clear()
school_db_item = db.session.query(School).join(User, User.id == School.psychologist_id).filter(User.id == current_user.id).filter(School.school==school).first()
education_types = school_db_item.education_type.split(',')
for _ in range(groups):
details_form.appeend_group()
for _ in range(classes):
details_form.appeend_class(education_types)
if details_form.continue_button.data and details_form.validate_on_submit():
for preschool_details in details_form.preschool_groups:
group = Group(name=preschool_details.group_name.data, number_of_pupils=preschool_details.group_size.data, school_id=school_db_item.id)
db.session.add(group)
for class_details in details_form.classes:
print(class_details.class_name.data)
c = Classes(name=class_details.class_name.data, number_of_students=class_details.class_size.data, class_type=class_details.class_type.data, school_id=school_db_item.id)
db.session.add(c)
db.session.commit()
details_form.classes.clear()
details_form.preschool_groups.clear()
flash('Detaliile au fost inregistrate')
return redirect(url_for('session_page'))
return render_template('detalii-scoala.html', details_form=details_form)
html:
<form action="" method="post">
{{ details_form.hidden_tag() }}
<table>
{% for preschool in details_form.preschool_groups %}
<tr>
<td><p>
{{ preschool.group_name(class_="form-control") }}<br>
{% for error in preschool.group_name.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
<td><p>
{{ preschool.group_size(class_="form-control") }}<br>
{% for error in preschool.group_size.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
</tr>
{% endfor %}
</table>
<br>
<table>
<tr>
<td>Denumire clasă</td>
<td>Nr. elevi înscrişi</td>
<td>Ciclul</td>
</tr>
{% for class in details_form.classes %}
<tr>
<td><p>
{{ class.class_name(class_="form-control") }}<br>
{% for error in class.class_name.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
<td><p>
{{ class.class_size(class_="form-control") }}<br>
{% for error in class.class_size.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
<td><p>
{{ class.class_type(class_="form-control") }}<br>
{% for error in class.class_type.errors %}
<span class="error">[{{ error }}]</span>
{% endfor %}
</p></td>
</tr>
{% endfor %}
</table>
<p>{{ details_form.continue_button(class_="btn btn-primary") }}</p>
</form>
Front end works, the only problem is when I try to add the data from thee form in the database.
The problem was that HTML fields were having the same name. To solve that I used request.form.getlist('name) to create the lists

Getting specific post category in Flask

I must get post if my category == academic (SelectField choice). But it doesn't work (posts are not shown). How can I get post data or form data for this?
I've tried
#categories.route("/category/academic")
def academic():
page = request.args.get('page', 1, type=int)
posts = Post.query.order_by(
Post.date_posted.desc()).filter(
Post.category == "Academic").paginate(page=page, per_page=5)
return render_template('academic.html', posts=posts)
and
#categories.route("/category/academic")
def academic():
form = PostForm()
page = request.args.get('page', 1, type=int)
post = Post(title=form.title.data,
content=form.content.data,
category=form.category.data)
posts = Post.query.order_by(
Post.date_posted.desc()).order_by(
post.category == "Academic").paginate(page=page, per_page=5)
return render_template('academic.html', posts=posts)
and
#categories.route("/category/academic")
def academic():
page = request.args.get('page', 1, type=int)
posts = Post.query.order_by(
Post.date_posted.desc()).filter(
**PostForm**.category == "Academic").paginate(page=page, per_page=5)
return render_template('academic.html', posts=posts)
Post.category
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False,
default=datetime.utcnow)
content = db.Column(db.Text, nullable=False)
category = db.Column(db.String(50))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
PostForm.category
class PostForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
content = TextAreaField('Content', validators=[DataRequired()])
category = SelectField('Category', validators=[DataRequired()], choices=[(
'Academic', 'Academic'), ('Art', 'Art')])
submit = SubmitField('Post')
Template (category.html)## This template for posts - Showing the category.html - All of template
{% extends "layout.html" %} {% block content %} {% for post in posts.items %}
<article class="media content-section">
<img
class="rounded-circle article-img"
src="{{ url_for('static', filename='profile_pics/' + post.author.image_file) }}"
/>
<div class="media-body">
<div class="article-metadata">
<a
class="mr-2"
href="{{ url_for('users.user_posts', username=post.author.username) }}"
>{{ post.author.username }}</a
>
<small class="text-muted">{{
post.date_posted.strftime("%Y-%m-%d")
}}</small>
<small class="article-category">
<mark
><a
class="mr-2"
href="{{ url_for('categories.category_route', category=post.category) }}"
>{{ post.category }}</a
></mark
>
</small>
</div>
<h2>
<a
class="article-title"
href="{{ url_for('posts.post', post_id=post.id) }}"
>{{ post.title }}</a
>
</h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
{% endfor %} {% for page_num in posts.iter_pages(left_edge=1, right_edge=1,
left_current=1, right_current=2) %} {% if page_num %} {% if posts.page ==
page_num %}
<a class="btn btn-info mb-4" href="{{ url_for('main.home', page=page_num) }}">{{
page_num
}}</a>
{% else %}
<a
class="btn btn-outline-info mb-4"
href="{{ url_for('main.home', page=page_num) }}"
>{{ page_num }}</a
>
{% endif %} {% else %} ... {% endif %} {% endfor %} {% endblock content %}
Doesn't work because posts are not shown.
Well this works fine here. I copied your model, and parts of your template, which I further simplified for testing purposes. It works all just fine and results in your browser adapt nicely to the nr of items per page. In example below it is set on 2, but it works with 5 as well. Bear in mind you can only use attributes that are covered in the model and your query. Currently you have multiple issues on that. I suspect that your template is causing that you don't see any results.
python code:
page = request.args.get('page', 1, type = int)
posts = Post.query.filter_by(category = 'Academic').paginate(page=page, per_page=2)
Template:
{% extends "layout.html" %}
{% block content %}
{% for post in posts.items %}
<a href="" > {{ post.title }} </a>
{{ post.category }}
<p> {{ post.content }} </p>
{% endfor %}
{% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
{% if page_num %}
{% if posts.page == page_num %}
<a class="btn btn-info mb-4" href="{{ url_for('home.home', page = page_num) }}">{{ page_num }}</a>
{% else %}
<a class="btn btn-outline-info mb-4" href="{{ url_for('home.home', page = page_num) }}"> {{ page_num }} </a>
{% endif %}
{% endif %}
{% endfor %}
{% endblock content %}

Django pagination filtered results CBV

How can I paginate using multiple filters in Django CBV? I have some filters in my view and form and I don't know how to paginate it. Everything that I've tried has failed.
Here my code.
models.py
class Lei(models.Model):
CHOICE_TIPO_LEI = (
('complementar', 'Lei complementar'),
('ordinaria', 'Lei ordinária'),
('decreto', 'Decreto'),
('portaria', 'Portaria'),
('convenio', 'Convênios Municipais'),
)
numero = models.CharField(max_length=6)
tipo_lei = models.CharField(u'Tipo do documento', max_length=15, choices=CHOICE_TIPO_LEI)
ano = models.CharField(max_length=4)
titulo = models.TextField()
arquivo = FileBrowseField("Arquivo PDF", max_length=200, extensions=[".pdf",".doc", ".xls", ".docx", ".xlsx"], directory="leis/", blank=True, null=True)
publicacao = models.DateTimeField(u'publicação', auto_now=True, blank=True)
class Meta:
db_table = "tb_lei"
verbose_name = "Lei"
verbose_name_plural = "Leis"
def __str__(self):
return self.titulo
views.py
class LeisListView(ComunsNoticiasMixin, ListView):
model = Lei
template_name = 'leis/leis.html'
context_object_name = 'leis'
def get_context_data(self, **kwargs):
context = super(LeisListView, self).get_context_data(**kwargs)
context["an"] = Lei.objects.values('ano').distinct().order_by('-ano')
context["tl"] = Lei.objects.values('tipo_lei').distinct().order_by('tipo_lei')
return context
class BuscaLeiListView(ComunsNoticiasMixin, ListView):
model = Lei
template_name = 'leis/busca-leis.html'
context_object_name = 'busca_leis'
paginate_by = 1
def get_queryset(self, **kwargs):
numero = self.request.GET.get('n')
ano = self.request.GET.get('a')
tipo_lei = self.request.GET.get('t')
palavra = self.request.GET.get('p')
leis = Lei.objects.all().order_by('-ano', '-numero')
if numero:
leis = leis.filter(numero=numero)
if ano:
leis = leis.filter(ano=ano)
if tipo_lei:
leis = leis.filter(tipo_lei=tipo_lei)
if palavra:
leis = leis.filter(titulo__icontains=palavra)
return leis
form.html
<form method="get" action="{% url 'leis:busca_lei_view' %}">
<div class="form-group">
<select name="t" class="form-control">
<option value="">Tipo do documento</option>
{% for l in tl %}
<option value="{{ l.tipo_lei }}">
{% if l.tipo_lei == "complementar" %} Leis complementares
{% elif l.tipo_lei == "ordinaria" %} Leis ordinárias
{% elif l.tipo_lei == "decreto" %} Decretos
{% elif l.tipo_lei == "convenio" %} Convênios municipais
{% elif l.tipo_lei == "portaria" %} Portarias
{% endif %}
</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<input name="n" type="text" class="form-control" placeholder="numero da lei, portaria ou decreto" size="10" maxlength="30">
</div>
<div class="form-group">
<select name="a" class="form-control">
<option value="">ano</option>
{% for l2 in an %}
<option value="{{ l2.ano }}">{{ l2.ano }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<button value="{{ search_term }}" class="btn btn-info">pesquisar</button>
</div>
<hr />
<div class="form-group">
<label for="t"><strong>Ou digite um termo a ser pesquisado</strong></label>
<input name="p" class="form-control" type="text" placeholder="digite um termo a ser pesquisado" size="20" maxlength="30">
</div>
<button value="{{ search_term }}" class="btn btn-info">Pesquisar</button>
result.html
<div class="row">
<div class="col-xs-12">
{% if busca_leis %}
{% for lb in busca_leis %}
<h4 ><a href="{{ lb.arquivo.url }}" class="text-primary">
{% if lb.tipo_lei == "complementar" %}Lei complementar n° {% elif lb.tipo_lei == "ordinaria" %} Lei ordinária nº {% elif lb.tipo_lei == "decreto" %} Decreto nº {% elif lb.tipo_lei == "convenio" %} Convênio municipal {% else %} Portaria nº{% endif %} {{ lb.numero }} de {{ lb.ano }}</a>
</h4>
<p class="post-content">{{ lb.titulo|safe }}</p>
<br />
{% endfor %}
<br />
{% else %}
<br /><br />
<div class="alert alert-warning" role="alert">
<h5>
O termo pesquisado não foi encontrado. Utilize os filtros para realizar a pesquisar novamente.
</h5>
voltar
</div>
{% endif %}
</div>
{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li>«</li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
The existing querystring is being dropped when you click on the pagination, so you need to have a way to carry that information through.
The best option would be to bring that information through.
Start by adding the "django.core.context_processors.request" to settings.py
## settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
)
Now, you have access to https://docs.djangoproject.com/en/1.8/ref/request-response/#querydict-objects.
In the template change the line:
<a href="?page={{ page_obj.next_page_number }}">
to
<a href="?page={{ page_obj.next_page_number }}{% for key, value in request.GET.items %}{% if key != page %}&{{key}}={{value}}{% endif %}{% endfor %}"
This will loop through the keys in the querystring and ignore the pa

Bad for-loop in django with Groups model, ManyToMany field

I want to display 1 button in the for-loop, but i get as many buttons as many i have created groups. So.. when i created 3 groups where i'm one of the members, i got 3 buttons under every group i have. The problem is with this first loop in my code, but i don't know how to solve this.
Problem is in loop:
{% for z in mem %}
When i create any memberships it's like:
m = Membership.objects.create(person="damian", group="name_group", leader=True) / or False
Thanks for any help!
groups.html:
{% for g in gr %}
<div class="jumbotron">
<div class="jumbo2">
<form method="POST" class="post-form"> {% csrf_token %}
<p id="name"><b>Group's name:</b> {{g.name}}</p><br>
{% for member in g.members.all %}
<p><b>Member:</b> {{member.name}} </p>
{% endfor %}
<br>
<span class="desc2">Group's description:</span>
<p id="desc">{{g.description}}</p><br>
{% for z in mem %}
{% if z.leader == False %}
<button style="float: right" type="submit" name = "leave" value = "{{g.name}}" class="save btn btn-default">Leave</button>
{% elif z.leader == True %}
<button style="float: right" type="submit" name = "delete" value = "{{g.name}}" class="save btn btn-default">Delete</button>
{% endif %}
{% endfor %}
</form>
<br><br>
<p>
{% if messages %}
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
{% endif %}
</p>
</div>
</div>
{% endfor %}
views.py:
cvs = Cv.objects.all()
cv = Cv.objects.filter(author = request.user)
per = Person.objects.all()
gr = Group.objects.filter(members__name=request.user)
perr = Person.objects.filter(name=request.user)
mem = Membership.objects.filter(group = gr, person = perr)
form = GroupForm()
context = {
'gr': gr,
'per':per,
'mem':mem,
'form': form,
'cvs':cvs,
'cv':cv,
}
return render(request, 'groups.html', context)
models.py:
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self): # __unicode__ on Python 2
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
description = models.TextField(max_length=350)
def __str__(self): # __unicode__ on Python 2
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
leader = models.BooleanField(default=False)
group = models.ForeignKey(Group)
Ok, i replace my groups and used only membership objects. Here's my working code:
{% for z in mem %}
<div class="jumbotron">
<div class="jumbo2">
<form method="POST" class="post-form"> {% csrf_token %}
<p id="name"><b>Group's name:</b> {{z.group}}</p><br>
{% for member in z.group.members.all %}
<p><b>Member:</b> {{member.name}} </p>
{% endfor %}
<br>
<span class="desc2">Group's description:</span>
<p id="desc">{{z.group.description}}</p><br>
{% if z.leader == False %}
<button style="float: right" type="submit" name = "leave" value = "{{z.group}}" class="save btn btn-default">Leave</button>
{% elif z.leader == True %}
<button style="float: right" type="submit" name = "delete" value = "{{z.group}}" class="save btn btn-default">Delete</button>
{% endif %}
</form>
<br><br>
<p>
</p>
</div>
</div>
{% endfor %}

Categories

Resources