Display unique values on flask jinja template - python

I have a query on my views.py:
query = db.session.query(Basket, Fruits).filter(Fruits.basket_id == Basket.id)
In the html template, I wish to display for each basket id (basket id here is unique), what are the fruits inside each basket, thus I used a nested for loop in my template.
I have tried on the html template:
{% for basket in query | unique %}
<p>{{ basket.Basket.id }}</p>
{% for fruits in query %}
<p>{% if basket.Basket.id == fruits.Basket.id %}
<p>{{ query.Fruits.fruit }}</p>
{% endif %}
{% endfor %}
But the unique basket id is not displayed.
I have thought of creating 2 queries so that I can put .distinct and display the unique basket id, then use the other query to display the fruits, but that didn't make sense to me because I still need all the information in the whole query. Beginner in flask btw.

You might be able to achieve that with a one to many relationship.
class Basket(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(100))
fruits = db.relationship('Fruit', backref='basket')
class Fruit(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100))
basket_id = db.Column(db.Integer, db.ForeignKey('basket.id'))
#app.route('/')
def baskets():
baskets = db.session.query(Basket).all()
return render_template('baskets.html', baskets=baskets )
Jinja2 Template:
{% for b in baskets %}
<ul>
<p>
{% b.name %}
</p>
{% for f in b.fruits %}
<li>{{ f.name }}</li>
{% endfor %}
</ul>
{% endfor %}

Related

Django query does not select related_name

I do have the following models in django:
class UserPayments(models.Model):
_DATABASE = "payments"
id = models.AutoField(primary_key=True)
paym_psp_id = models.ForeignKey(ConfigPSP, null=True, on_delete=models.SET_NULL)
[...]
class InvoiceNumbers(models.Model):
_DATABASE = "payments"
id = models.AutoField(primary_key=True)
inv_date = models.DateField(null=False)
inv_payment_id = models.ForeignKey(UserPayments, null=True, on_delete=models.DO_NOTHING, related_name='paym_invoice_meta')
[...]
As you can see they are related with "related_name" definition in the InvoiceNumbers model.
When I no do a query in django like:
payments = UserPayments.objects.filter(paym_user_id=user_id)
And iterate through this query in a template
{% for inv in payments %}
{% for meta in inv.paym_invoice_meta %}
{{ meta.inv_invoice_hash }}
{% endfor %}
{% endfor %}
I get the template error that pay_invoice_meta is not iterable. With a manual select statement including the left outer join I get all the results.
What am I missing here? How can I force the query to select the values from InvoiceNumbers?
Call the all method of the related object to return a QuerySet:
{% for inv in payments %}
{% for meta in inv.paym_invoice_meta.all %}
{{ meta.inv_invoice_hash }}
{% endfor %}
{% endfor %}

Flask, Join two models with foreign key

my two models are
class Users (db.Model):
UserId = db.Column(db.INTEGER, primary_key=True,autoincrement=True)
UserName = db.Column(db.String(25),nullable=False, unique=True)
Email = db.Column(db.String,nullable=False,unique=True)
plan = db.relationship(
'Messages',
collection_class=attribute_mapped_collection('language'),
cascade="all,delete"
)
class Messages (db.Model):
MessageId = db.Column(db.INTEGER,primary_key=True,autoincrement=True)
SenderId = db.Column(db.INTEGER,db.ForeignKey('Users.UserId'),nullable=False)
language = db.Column(db.Enum('de', 'en'), nullable=False)
Now, My view looks like:
def premium():
usr_obj = models.Users.query.join(models.Messages)\
.order_by(models.Users.UserId.desc())
return render_template('user_plan.html', user=usr_obj)
My user_html is like:
{% for a in user %}
{{ a.UserName }} </br> {{ a.SenderID }} </br>
{% endfor %}
It is giving me only value of {{ a.UserName }} and not of {{ a.SenderID }}, why??
if you want only senderId and UserName from this join,you can try this:
obj= Users.query.with_entities(Users.UserName,Messages.SenderId
).join(Messages,Messages.SenderId==Users.UserId
).order_by(Users.UserId.desc()
).all()
explanation:-
we are applying join on Messages.SenderId and Users.UserId
with_entities: it means we only want UserName, SenderId from this join.
you can use for loop to access UserName and SenderId from this join.
like this:
for o in obj:
print o.UserName,o.SenderId
i hope this is solution of your problem.Use it according to your problem case.
One can use:
{% for a in user %}
{{ a.UserName }} </br> {{ a.plan[g.current_lang].SenderID }} </br>
{% endfor %}

Foreign key relation in Django template

I know this question is asked before many times but I still can't solve it.
model.py
class Awb (models.Model):
awb_id = models.CharField(primary_key=True, max_length=50)
awb_shipment_date = models.DateTimeField()
awb_shipper = models.CharField(max_length=250)
awb_sender_contact = models.CharField(max_length= 50)
class History (models.Model):
history_id = models.AutoField(primary_key=True)
awb = models.ForeignKey(Awb)
history_city_hub = models.CharField(max_length=250)
history_name_receiver = models.CharField(max_length=250)
view.py
def awb_list_view(request):
data = {}
data['awb'] = Awb.objects.all()
data['history'] = History.objects.all()
return render(request, 'portal/awb-list.html', data)
templates
{% for s in awb.history_set.all %}
{{ s.awb_id }}
{{ s.history_id }}
{% endfor %}
When I tried it with this code, there is no results in templates. I want to show awb_id and history_id in templates. Could you help me?
First let's take a look at the view code...
def awb_list_view(request):
data = {}
data['awb'] = Awb.objects.all()
data['history'] = History.objects.all()
return render(request, 'portal/awb-list.html', data)
The context dictionary being passed to the template contains an item with key 'awb' and respective QuerySet Awb.objects.all().
Now let's take a look at the template for loop...
{% for s in awb.history_set.all %}
This opening for loop template tag is trying to produce a reverse set of History objects. In order to achieve this, we would need a single AWB object instance. Instead, the 'awb' variable is a QuerySet which was passed as context to the template.
If the goal of this code is to show all AWB objects with their related History objects, the following template code should be valid.
{% for awb_obj in awb %}
{% for history_obj in awb_obj.history_set.all %}
{{ awb_obj.id }}
{{ history_obj.id }}
{% endfor %}
{% endfor %}
The Awb.history_set.all only applies to one Awb object, not a queryset.
This would work:
data['awb'] = Awb.objects.first() # If the first one has history
or:
Loop through all the Awb objects in the template to access the history_set for each one.
{% for a in awb %}
awb: {{ a.awb_id }}<br>
{% for h in a.history_set.all %}
history: {{ h.history_id }}<br>
{% endfor %}
{% endfor %}

Generate a dynamic form using flask-wtf and sqlalchemy

I have a webapp that allows users to create their own fields to be rendered in a form later on.
I have a model Formfield like so:
class Formfield(db.Model):
id = db.Column(db.Integer, primary_key = True)
form_id = db.Column(db.Integer, db.ForeignKey('formbooking.id'))
label = db.Column(db.String(80))
placeholder_text = db.Column(db.String(80))
help_text = db.Column(db.String(500))
box_checked = db.Column(db.Boolean, nullable = True, default = False)
options = db.Column(db.String) # JSON goes here?
answer = db.Column(db.String)
required = db.Column(db.Boolean, nullable = False, default = False)
order = db.Column(db.Integer)
fieldtype = db.Column(db.Integer)
that I use to represent a field, whatever the kind (checkbox, input, more in the future).
As you can see, every field has a FK to a form_id.
I’m trying to generate a dynamic form for a given form_id.
The catch is that I need to determine the type of field to render for every Formfield.
So I also need to process the fieldtype at some point.
I guess a solution would be to somehow pass the form_id to a function in my Form class.
I have no clue how to do it or where to look for a solution.
Any help would be very appreciated!
I think I managed to create dynamic forms with the idea from here https://groups.google.com/forum/#!topic/wtforms/cJl3aqzZieA
you have to create a dynamic form at view function, fetch the form field you want to get, and iterate every field to construct this form object. I used for fieldtypes simple text instead of integer values. Since it seems easy to read at code level.
class FormView(MethodView):
def get(self):
class DynamicForm(wtforms.Form): pass
dform = main.models.Form.objects.get(name="name2")
name = dform.name
for f in dform.fields:
print f.label
setattr(DynamicForm , f.label, self.getField(f))
d = DynamicForm() # Dont forget to instantiate your new form before rendering
for field in d:
print field # you can see html output of fields
return render_template("customform.html", form=d)
def getField(self, field):
if field.fieldtype == "text":
return TextField(field.label)
if field.fieldtype == "password":
return PasswordField(field.label)
# can extend if clauses at every new fieldtype
for a simple form render jinja template 'forms.html'
{% macro render(form) -%}
<fieldset>
{% for field in form %}
{% if field.type in ['CSRFTokenField', 'HiddenField'] %}
{{ field() }}
{% else %}
<div class="form-group {% if field.errors %}error{% endif %}">
{{ field.label }}
<div class="input">
{% if field.name == "body" %}
{{ field(rows=10, cols=40) }}
{% else %}
{{ field() }}
{% endif %}
{% if field.errors or field.help_text %}
<span class="help-inline">
{% if field.errors %}
{{ field.errors|join(' ') }}
{% else %}
{{ field.help_text }}
{% endif %}
</span>
{% endif %}
</div>
</div>
{% endif %}
{% endfor %}
</fieldset>
{% endmacro %}
and customform.html is like this
{% extends "base.html" %}
{% import "forms.html" as forms %}
{% block content %}
{{ forms.render(form) }}
{% endblock %}

Returning more than one field from Django model

How would one go about returning more than one field from a Django model declaration?
For instance: I have defined:
class C_I(models.Model):
c_id = models.CharField('c_id', max_length=12)
name = models.CharField('name', max_length=100)
def __str__(self):
return '%s' % (self.name)
which I can use, when called in a views.py function to return
{{ c_index }}
{% for c in c_index %}
<div class='c-index-item' c-id=''>
<p>{{ c.name }}</p>
</div>
{% endfor %}
from a template. This is being called in my views.py like so:
c_index = C_I.objects.all()
t = get_template('index.html')
c = Context({'c_index': c_index})
html = t.render(c)
How would I also include the c_id defined in the model above, so that I can include {{c.name}} and {{c.c_id}} in my template? When I remove the str method, I appear to get all of the results, however, it just returns blank entries in the template and will not let me reference the individual components of the object.
What you have is fine. Your template should be:
{% for c in c_index %}
<div class='c-index-item' c-id='{{ c.c_id }}'>
<p>{{ c.name }}</p>
</div>
{% endfor %}

Categories

Resources