Following is the simple database model i have:
class Notes(db.Model):
text = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
Now in the url handler, i send all the notes to the template as follows:
class MainPage(webapp2.RequestHandler):
def get(self):
notes = Notes.all()
self.render_template("index.html", {'notes':notes})
In the template i am using jinja2 templating engine, i want the id of each of the notes to be printed, so that i can embed an edit link, somewhat like this:
{% for note in notes %}
<p>
{{ note.text }} <br>
{{ note.date }} <br>
(edit )
{% endfor %}
But the trouble is, i dont see anything printed, in place of note.key.id
As per the docs over here key class represents a unique key for a database entity and this has a method id, its a numeric value. for a single note from the collection of notes i want the id of the note.
If i use the django templating engine i get the values {{ notes.key.id }} printed, but with jinja2 i dont see it.
How can i do this?
Well replace the href line with the following:
(edit )
This shall be enough.
Related
Is there any way to completely turn off django auto_escaping when rendering a template within the view code (for an email for example):
from django.template import Context, Template
subject_template_string = "Hi {{ customer.name }}"
subject_template = Template(subject)
context = Context({'customer':MyCustomerModel.objects.get(pk=1)})
subject = subject_template.render(context)
If customer.name is something like "Jack & Jill" - the subject looks like "Hi Jack &\amp; Jill" (without the backslash!)
is there something like
subject = subject_template.render(context, autoescape=False)
edit: The actual templates are created by the client in the database, I'm hoping to avoid having to say add |safe to all templates where this might happen...
Disabling it globally is usually a bad idea since you can easily forget it. I would recommend using the templatetag to disable it for that portion of your template instead.
Something like this:
{% autoescape off %}
This will not be auto-escaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}
How about using mark_safe:
Explicitly mark a string as safe for (HTML) output purposes. The
returned object can be used everywhere a string or unicode object is
appropriate.
It marks a string as safe, so, you should take customer.name out and pass to the template:
from django.utils.safestring import mark_safe
customer = MyCustomerModel.objects.get(pk=1)
context = Context({'customer_name': mark_safe(customer.name)})
subject = subject_template.render(context)
Though, control what is safe or not is better to do inside the template itself, that's why using autoescape should be preffered.
Use Django's autoescape tag:
{% autoescape off %}
{{ body }}
{% endautoescape %}
for more info, check out the docs here.
This is untested, but based on source code review it looks like the context object can take autoescape as a key.
context = Context({'customer':MyCustomerModel.objects.get(pk=1), 'autoescape': False})
subject = subject_template.render(context)
That said, that's a pretty sweeping change. If you know what values the templates might be looking for, it's probably better to use mark_safe on those values and pass in the predefined options. That would have the added benefit of not risking the possibility of the client template calling a method with side effects on the customer. The first time someone writes a template and puts in {{ customer.delete }}, you have a problem.
Just came back to answer my own question with a simple solution, and there were already 4 answers.. thanks.
This is what I've gone with:
subject_template = Template(u'{%% autoescape off %%}%s{%% endautoescape %%}' % email.subject)
This is my model structure.
Institution
- name
- logo
- ....
Course
- Owner ( foriegnKey with Institution )
- name
- terms
- .....
So now, am just calling data's like.
courses = Course.objects.filter(name__icontains=query).values('id','name','terms','owner__name', 'owner__logo')
And trying to display the owner__logo as {{data.owner__logo.url}}. But its not working, as the img src shows (unknown). But when this Institution logo thing works on some other view when i directly call it. but when i call via relationship its not working.
If i use {{data.owner__logo}} then it just passes the url without the full path. How to make this work, please help !
An approach that worked for me after I've experimented is...
# Use the FK object id (owner_id) since you're dealing with a FK.
courses = Course.objects.filter(name__icontains=query).values('id','name','terms','owner_id')
If you should print the courses dictionary you'll see the fields it contains for each course. In this case, you'll see the FK with the id listed for that object. Example:
{'id': 10, 'owner_id': 7, 'name': 'Random', 'terms': 'Anything', ...}
What I did from here since the courses object is a dictionary, I've added a new key with with the value being the logo url.
for course in courses:
# First is to get the owner object with the course['owner_id']
owner = Institution.objects.get(id=course['owner_id'])
# From the owner object, you have access to the logo and it's URL
# Creating a new key called 'logo_url' and assigning the owner logo URL to it
course['logo_url'] = owner.logo.url
# Add the courses dictionary to the context variable
context['courses'] = courses
Then within your template, you can access the logo_url for each course.
{% for course in courses %}
<img src="{{ course.logo_url }}"/>
{% endfor %}
OPTION #2: A MORE EFFICIENT WAY
The next option here is to use a template filter to get the Institution object's logo url in just one go while you loop over the items in the template.
In your custom_tags.py file:
from django import template
from django.shortcuts import get_object_or_404
register = template.Library()
#register.filter
def get_logo_url(bypass, owner_id):
# owner = Institution.objects.get(id=owner_id)
# or
owner = get_object_or_404(Institution, id=owner_id) # Recommended
if owner:
url = owner.logo.url
else:
url = ""
return url
In your template and for loop.
{% load custom_tags %} # Must do to be able to use the custom filter
{% for course in courses %}
{% with logo_url=""|get_logo_url:course.owner_id %}
<img src="{{ logo_url }}" />
{% endwith %}
{% endfor %}
If you're not familiar with django custom tags and filters, you can see the doc here.
I am new to Flask and SQLalchemy. Want to have web page with individual photo that shows all tags assigned to that photo.
I have SQLalchemy working fine with MYSQL db. Nicely retrieves records etc.
I need help with flask/SQLalchemy work flow:
model -> view (input from url eg view / photo id) -> template -> web page
The models are as follows:
class Photos(db.Model):
id = db.Column(db.Integer, primary_key=True)
filename = db.Column(db.String(100))
tags = db.relationship(
'Tags',
secondary=photo_tags,
backref='photos')
class Tags(db.Model):
id = db.Column(db.Integer, primary_key=True)
tagname = db.Column(db.String(100))
photo_tags = db.Table('photo_tags',
db.Column('tag_id', db.Integer, db.ForeignKey('tags.id')),
db.Column('photo_id', db.Integer, db.ForeignKey('photos.id'))
)
My view is as follows:
#app.route('/phototags/<int:id>')
##login_required
def phototags(id=None):
photo_tags = Tags.query.filter(Tags.photos).filter(id == id).all()
return render_template(
'phototags.html',
title='PhotoTags',
message='Your application description page.',
photo_tags = photo_tags
)
My template is as follows:
{% extends "layout.html" %}
{% block content %}
<h2>{{ title }}.</h2>
<h3>{{ message }}</h3>
{% for phototag in photo_tags %}
<div style="float:left; class=" img-responsive">
<p>photo</p>
<p></p>tag</p>
<img src="static/photos/{{ phototag.id }}" width="100" height="100">
</div>
{% endfor %}
{% endblock %}
I am pretty sure the models and association table/model are setup properly.
The template is not perfect, as it currently appears to show tag ids for photo ids. I have tried to do 'phototag.photo_id' or 'phototag.filename' but doesn't come out. Obviously view query is not putting that through.
So the view is what i need help with. Is the query correct? and is it getting url passed parameter for photo_id correctly?
My test data is simple. I have a single Photo record with photos.id = 1
This has 2 related Phototags records: phototags.id = 1 (tag.id = 1), phototags.id = 2 (tag.id = 2)
When I pass url http://localhost:5555/phototags/1 my view query passes tag ids, but changing the passed parameter always gets the same tag ids eg phototags/2 also gets the same two tags. So query is obviously not correct.
I have looked at scores of examples and they all subtly different than what I want. None of the examples/tutorials/SO questions/answers i have seen show how the model, view and template work together to get what I want. They are either:
getting opposite eg equivalent of photos by tag (want tags by photo)
are just query that gets the tags by photo (i don't even think i am getting that)
have another SQLalchemy notation that includes 'sessions' or 'base' instead of 'db.model'
What I want as output is a photo id so i can show photo and its name etc and also show a list of tags associated with that photo eg as a comma separated list.
I am stumped to find a demo/example/tutorial/github project that walks me through what i need for workflow.
Can anyone show me example of view that can get photo id from url parameter and then query my models to get the associated tags?
It seems more appropriate to query a photo instead of photo_tags from what you describe about your use case.
With the view function
#app.route('/phototags/<int:id>')
def phototags(id=None):
photo = Photo.query.get(id)
return render_template(
'phototags.html',
title='PhotoTags',
message='Your application description page.',
photo = photo
)
you can then display the photo and iterate its tags using the 'tags' relationship in the html template:
{% extends "layout.html" %}
{% block content %}
<h2>{{ title }}.</h2>
<h3>{{ message }}</h3>
<img src="static/photos/{{ photo.id }}" width="100" height="100">
{% for phototag in photo.tags %}
<div style="float:left; class=" img-responsive">
<p>photo</p>
<p></p>tag</p>
</div>
{% endfor %}
{% endblock %}
Note that I used the get function in the query for the Photo. It's basically the same as
Photo.query.filter(id == id).first()
Renaming the view function and the template from phototags to photo would also make sense.
If you wanted to display all images for a tag you have to reverse the logic, querying for a tag and iterating over the photos. Should be possible, because you defined a backref.
Why Flask + Mongoengine doesnot allow to show db items that is not fully correspond to db schema model?
Here is my class Tweet (in models.py of Flask app) inherited from Post, text and lang fields are named the same, as they come from Twitter API with every tweet.
class Tweet(Post):
text = db.StringField(required=True)
lang = db.StringField(max_length=255, required=True)
When i am saving Tweet post via admin it is saved to Mongodb, and i can render it in list.html:
{% for tweet in tweets %}
<b>Tweets list</b>
<h2>{{ tweet.text }}</h2>
{% if tweet.post_type == 'Tweet' %}
<b>{{ tweet.text }}</b>
<p>{{ tweet.lang }}</p>
{% endif %}
{% endfor %}
The problem: in that collection i stored a lot of full tweets with all fields, and all these tweets has text and lang fields, but it is not showed in browser.
I mined tweets with external script and now want to use Flask to query existing collection to show tweets in web interface. And i don't want to define all tweet structure in ORM.
I have Robomongo and i see manually added from admin posts near the tweets, mined by Twitter python library. Fields are named "text" and "lang" because in tweet JSON they are named the same.
Ensure that a Tweet is a DynamicDocument and then loop the Tweet._dynamic_fields attribute to get the name of any dynamic fields.
Something like:
{% for tweet in tweets %}
<b>Tweets list</b>
<h2>{{ tweet.text }}</h2>
{% if tweet.post_type == 'Tweet' %}
<b>{{ tweet.text }}</b>
<p>{{ tweet.lang }}</p>
{% for field in tweet._dynamic_fields -%}
<p>{{ tweet[field] }}</p>
{%- endfor %}
{% endif %}
{% endfor %}
Thats untested and I'm not 100% sure on how you dynamically get an attr in jinja2.
Answer by Ross is correct, i wish now to clarify the process to get all working.
I guessed that if a JSON document has an "_cls" : "Post.Tweet" attr it shows. The problem was that in tweets i mined no such attribute. I have added it to existing tweet using Robomongo for testing and it now appears in the list, near the simple manually added items!
Before it shows i solved another error: i needed to map models to tweet structure
so i need the tweet have a slug, for this i added "slug" : "Detective".
Result is showed, but nested JSON objects appears as clunky json mess.
The question now is how do achieve the same result without changing mined tweets, i need to change code: avoid checking _cls for tweets and setup slug to some existing field.
So what parts of code should i change&?
I'm using Google App Engine 1.8.3 - Python 2.7 and NDB API as my datastore
Suppose I have a list of group entities displayed on a html table.
And I want to click the name of an individual group to edit the group's information.
What should the key/id of this group be, which one should I use? Please take a look at below
Here's my Model:
class Group(ndb.Model):
name = ndb.StringProperty()
description = ndb.StringProperty()
In my html:
......
{% for group in groups %}
<tr>
<td>
<a href="/editGroup?id={{ ????????????? }}" {{ group.name}} </a>
</td>
<td>
{{ group.description}}
</td>
</tr>
{% endfor %}
......
In the ????? inside the <a> tag, what should I put? what should I pass it back to the server? group.key? group.key.id()? or I have to add the Property to Group model as a key property like groupId = ndb.IntegerProperty()?
I'm thinking about using the entity's key, but I couldn't find a way to display the key in the html from 'group', like group.something_to_get_the_key().
I was able to get the numeric id using group.key.id(), but according to https://developers.google.com/appengine/docs/python/ndb/entities#numeric_keys
numeric ids might not be unique.
Thanks
In NDB, keys have a urlsafe() method which produces a string suitable for use in templates and passing to URLs:
{{ group.key.urlsafe }}
This is documented on the same page you already link to.