Django: How to position a page when using Django templates and links - django

I have this in my template:
<div id="comment-{{ post_comment.id }}">
<a title="Comment was useful" href="/useful-comment/{{ blog_post.id }}/{{ post_comment.id }}/">
When the user clicks on this link, the method useful_comment(blog_post_id, post_comment_id) is called and at when it returns it loads the same template again. I then want to scroll the page down to #comment-{{ post_comment.id }}, but how do I do that if I load my template like so:
arguments = dict(user = request.user, blog_post = blog_post)
t = loader.get_template('blog-post-template.html')
c = RequestContext(request, args)
return HttpResponse(t.render(c))
This is related to Django: How do I position a page when using Django templates, but in that question they are using forms and only scrolling down to a static section of the page.

You should add an #anchor to your link's href. In your case there will be different anchors (<a name="comment_123"></a>, for example) for all your comments, so be sure link points to correct anchor.
This is nothing to do with Django, just old good HTML.

Related

Set a variable through a drop down list in django

def scan(request):
scan = Stock.objects.all()
hammer = Stock.objects.filter(Hammer=100)
belthold = Stock.objects.filter(Belthold=100)
context = {'All':scan, 'Belthold':belthold, 'Hammer':hammer
}
return render(request, 'scanner/scan.html', context)
This is my views.py file. I want to add a dropdown list to my html page containing the context dictionary which changes the query filters according.
This is my current html page:
{% for i in Hammer %}
<tr>
<td>{{i.script}}</td>
<td>{{i.open}}</td>
<td>{{i.high}}</td>
<td>{{i.low}}</td>
<td>{{i.close}}</td>
<td>{{i.Volume}}</td>
<td>{{i.Change}}</td>
</tr>
{% endfor %}
The 'Hammer' need to be replaced by whatever selection is made from the dropdown list.
THANKS!!
You cannot dynamically change Hammer in a template for loop. You can use the approach below or change the approach as to how you want everything displayed.
You have to use Javascript for that. You first need to give id's to all the tags you have in the for loop.
<td id="{{i.script}}_myid"> ...
Then with Javascript access the change in the dropdown menu's value and then update the respective td's accordingly:
document.getElementbyId('dropdown').addEventListener('change', function(e) {
// Change td's here: document.getElementbyId(..._myid).innerHTML = "" })
To pass Hammer in your JS you can either do an inline script (which many dont recommend) or a separate JS file added as a script tag below. You can use serializers to pass on the objects from Python to JS.

How to pass a template tag from one template to another in django 2

I am new to Django, and template tags and HTML and have a template where I use a for loop to fill out bootstrap cards from a database. In the model I has a field Resume_link that has a PDF file. All I want to is have the PDF file displayed in a different template file and not in the card where it is too small to read. (Since I am in the loop when someone clicks the link, I just want the specific resume connected to that card to be shown in the new template.) So all I think I should need to do is somehow either pass the the index of the loop, or another variable that identifies the correct database entry. But I think I am missing something fundamental and don't understand how to pass the value of a template tag in one template another template. Is there some way to pass a variable along with the url to a view so the variable can be used to make a new template tag in the desired template?
{% for key in myres %}
...fill out other parts of cards and create the below link...
<a href="{% url "show_pdf" %}" style="font-size: 20px">
{% endfor %}
where show_pdf is the view where I want to show the whole PDF file.
and that template show_pdf is
What I would like to do is be able to pass the key.Resume_link.url, or if not that the pk for that database table to the show_pdf template.
The view for show_pdf is
def show_pdf(request):
template = 'show_pdf.html'
myres=Research.objects.all()
context = {'myres': myres}
return render(request,'mainapp/show_pdf.html', context)
you can pass the current pdf id in the url and access it.
def show_pdf(request, pdf_id):
template = 'show_pdf.html'
myres=Research.objects.get(id=pdf_id)
context = {'myres': myres}
return render(request,'mainapp/show_pdf.html', context)
In you urls.py you must write like this
path('show_pdf/?P<int:pdf_id>/', views.show_pdf, name="show_pdf")
In HTML write <a href="{% url "show_pdf" key.id %}">
Instead of:
<a href="{% url "show_pdf" %}">
... you would include a parameter, e.g.:
<a href="{% url "show_pdf" pdf_id %}">
The resulting URL would now be formatted as indicated by the corresponding urlconf entry, for instance:
http://my.web.site/resumes/show_pdf/1343
(if pdf_id = 1343 ...)
You must specify as many parameters as the corresponding urlconf entry expects, and you may use either positional or keyword syntax (but not both).
Then, when the user clicks on the link, the View specified in that urlconf will get control, and it will have the specified parameter value (1343 ...) as one of its arguments. You'd select the PDF and send it to the template to be properly presented to the user.

Using AngularJS template tags in Django [duplicate]

I want to use AngularJS with Django however they both use {{ }} as their template tags. Is there an easy way to change one of the two to use some other custom templating tag?
For Angular 1.0 you should use the $interpolateProvider apis to configure the interpolation symbols: http://docs.angularjs.org/api/ng.$interpolateProvider.
Something like this should do the trick:
myModule.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
Keep in mind two things:
mixing server-side and client-side templates is rarely a good idea and should be used with caution. The main issues are: maintainability (hard to read) and security (double interpolation could expose a new security vector - e.g. while escaping of serverside and clientside templating by themselves might be secure, their combination might not be).
if you start using third-party directives (components) that use {{ }} in their templates then your configuration will break them. (fix pending)
While there is nothing we can do about the first issue, except for warning people, we do need to address the second issue.
you can maybe try verbatim Django template tag
and use it like this :
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
{% verbatim %}
<div ng-app="">
<p>10 is {{ 5 + 5 }}</p>
</div>
{% endverbatim %}
If you did separate sections of page properly then you can easily use angularjs tags in "raw" tag scope.
In jinja2
{% raw %}
// here you can write angularjs template tags.
{% endraw %}
In Django template (above 1.5)
{% verbatim %}
// here you can write angularjs template tags.
{% endverbatim %}
We created a very simple filter in Django 'ng' that makes it easy to mix the two:
foo.html:
...
<div>
{{ django_context_var }}
{{ 'angularScopeVar' | ng }}
{{ 'angularScopeFunction()' | ng }}
</div>
...
The ng filter looks like this:
from django import template
from django.utils import safestring
register = template.Library()
#register.filter(name='ng')
def Angularify(value):
return safestring.mark_safe('{{%s}}' % value)
So I got some great help in the Angular IRC channel today. It turns out you can change Angular's template tags very easily. The necessary snippets below should be included after your angular include (the given example appears on their mailing lists and would use (()) as the new template tags, substitute for your own):
angular.markup('(())', function(text, textNode, parentElement){
if (parentElement[0].nodeName.toLowerCase() == 'script') return;
text = text.replace(/\(\(/g,'{{').replace(/\)\)/g, '}}');
textNode.text(text);
return angular.markup('{{}}').call(this, text, textNode, parentElement);
});
angular.attrMarkup('(())', function(value, name, element){
value = value.replace(/\(\(/g,'{{').replace(/\)\)/, '}}');
element[0].setAttribute(name, value);
return angular.attrMarkup('{{}}').call(this, value, name, element);
});
Also, I was pointed to an upcoming enhancement that will expose startSymbol and endSymbol properties that can be set to whatever tags you desire.
I vote against using double parentheses (()) as template tag. It may work well as long as no function call is involved but when tried the following
ng:disabled=(($invalidWidgets.visible()))
with Firefox (10.0.2) on Mac I got a terribly long error instead of the intended logic. <[]> went well for me, at least up until now.
Edit 2012-03-29:
Please note that $invalidWidgets is deprecated. However I'd still use another wrapper than double braces. For any angular version higher than 0.10.7 (I guess) you could change the wrapper a lot easier in your app / module definition:
angular.module('YourAppName', [], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<[');
$interpolateProvider.endSymbol(']>');
});
API docs.
You could always use ng-bind instead of {{ }}
http://docs.angularjs.org/api/ng/directive/ngBind
<span ng-bind="name"></span>
I found the code below helpful. I found the code here: http://djangosnippets.org/snippets/2787/
"""
filename: angularjs.py
Usage:
{% ng Some.angular.scope.content %}
e.g.
{% load angularjs %}
<div ng-init="yourName = 'foobar'">
<p>{% ng yourName %}</p>
</div>
"""
from django import template
register = template.Library()
class AngularJS(template.Node):
def __init__(self, bits):
self.ng = bits
def render(self, ctx):
return "{{%s}}" % " ".join(self.ng[1:])
def do_angular(parser, token):
bits = token.split_contents()
return AngularJS(bits)
register.tag('ng', do_angular)
If you use django 1.5 and newer use:
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
If you are stuck with django 1.2 on appengine extend the django syntax with the verbatim template command like this ...
from django import template
register = template.Library()
class VerbatimNode(template.Node):
def __init__(self, text):
self.text = text
def render(self, context):
return self.text
#register.tag
def verbatim(parser, token):
text = []
while 1:
token = parser.tokens.pop(0)
if token.contents == 'endverbatim':
break
if token.token_type == template.TOKEN_VAR:
text.append('{{')
elif token.token_type == template.TOKEN_BLOCK:
text.append('{%')
text.append(token.contents)
if token.token_type == template.TOKEN_VAR:
text.append('}}')
elif token.token_type == template.TOKEN_BLOCK:
text.append('%}')
return VerbatimNode(''.join(text))
In your file use:
from google.appengine.ext.webapp import template
template.register_template_library('utilities.verbatim_template_tag')
Source:
http://bamboobig.blogspot.co.at/2011/09/notebook-using-jquery-templates-in.html
You can tell Django to output {{ and }}, as well as other reserved template strings by using the {% templatetag %} tag.
For instance, using {% templatetag openvariable %} would output {{.
I would stick with a solution that uses both django tags {{}} as well angularjs {{}} with a either a verbatim section or templatetag.
That is simply because you can change the way angularjs works (as mentioned) via the $interpolateProvider.startSymbol $interpolateProvider.endSymbol but if you start to use other angularjs components like the ui-bootstrap you will find that some of the templates are ALREADY built with standard angularjs tags {{ }}.
For example look at https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html.
If you do any server-side interpolation, the only correct way to do this is with <>
$interpolateProvider.startSymbol('<{').endSymbol('}>');
Anything else is an XSS vector.
This is because any Angular delimiters which are not escaped by Django can be entered by the user into the interpolated string; if someone sets their username as "{{evil_code}}", Angular will happily run it. If you use a character than Django escapes, however, this won't happen.

djangocms-snippet which contains {% %} doesnot show up as placeholder content

I am trying to make my footer a editable from frontend.. using placeholder and inserting footer snippet.
yet, my footer snippet contains django template language
e.g.
Terms and Conditions
as a result, the placeholder content is not showing up, if i remove the django specific things
Terms and Conditions
it is working.
how can I make it work with django reverse url?
I could have given hard coded path but i want the path translatable so i need to reverse by url's name.
If I've got you right, just create custom tag and store templates in database:
from django.template import RequestContext, Template
#register.simple_tag
def footer(request):
snippet = Snippet.object.get(name='footer')
template = Template(snippet.html)
return template.render(RequestContext(request))
{% footer request %}
use this syntax:
{% url 'terms_conditions' as the_url %}
Terms and Conditions
use smartsnippets
These has the capability of rendering django tags

Showing 'cancel' on login page to return user to where they were (using django.contrib.auth)

We are using the #login_required decorator so that users see a login page if they try to access a url for which they need to be authenticated.
We want to show a 'cancel' button on the login page, which should return the user to whichever page they were on when they tried to access the url (by clicking a link etc - we don't need to deal with them manually entering the url).
At the moment our login.html looks for a request parameter 'login_cancel_url' and if present uses that (otherwise the home page).
However, this means we have to manually pass this parameter (set to the url of the current page) whenever we show a link or button that leads to an 'authentication required' url.
Is there a more elegant way to do this?
Thanks, Martin
Well you can try get the referrer header from the request but as far as I am aware, it's browser dependent and is not very reliable so the way you are doing it is probably best. You could try make life easier by creating template tags to avoid having to rewrite the return URL manually.
You are easily able to get the current URL from django's request object on any page, so instead of setting it manually on the link, you could write a snippet of html:
link_to_login.html
<!-- You should probably get /login/ using the {% url ... %} template tag -->
<a href="/login/?login_cancel_url={{ request.path|urlencode }}">
Login Page</a>
and use the {% include "link_to_login.html"%} template tag.
Alternatively, If the text needs to be different depending on the link you can instead create an inclusion template tag:
templatetags/extra_auth_tags.py
#register.inclusion_tag('templates/extra_auth_tags/login_link.html')
def login_link(context, text=None):
return {
'text':text
}
templates/extra_auth_tags/login_link.html
<!-- You should probably get /login/ using the {% url ... %} template tag -->
<a href="/login/?login_cancel_url={{ request.path|urlencode }}">
{% if text %}
{{ text }}
{% else %}
Some Default Text
{% endif %}
</a>
and then call it in your templates as {% login_link text="Check you messages" %}. Be aware that keyword arguments for inclusion tags are only supported in the django dev version so you might need to write the template tag by hand.