Dynamic Display in Base HTML using DJango - html

I am new to DJango and i am creating a Website. I have created a base HTML page with a NAV bar which will be used across all pages. I want to display the message "Welcome 'username'" as the first line across all pages.
I had written the following code in views.py
def getusername(request):
uname=request.getusername()
return render(request,'main.html',{'uname':uname})
in the main.html after defining the title and nave bar, i have the following html code
<span class="label label-default">Welcome{{uname}}</span>
When i run this code, I am able to view the NavBar in all pages tat extends the base page(main.html)
but the welcome message does not fetch the username.
I have configured the following in urls.py
path("", views.getusername,name='getusername')
Note: Even when i hardcode a string to be returned from views.py, the string is not displayed as part of the welcome message

In every template you have access to user object.
You can check if user is authenticated:
{% if user.is_authenticated %}
Welcome, {{ user.username }}
{% else %}
# show register or(and) login button
{% endif %}

Related

How redirect to alogin page in html Django if user is not authinticated

How to in HtMl to redirect user if it is noit registered using this template. I want to redirect if not registered to Login page
{% if user.is_authenticated %}
<p>Authenticated user</p>
{% else %}
redirect to 'login' page
{% endif %}
I have in settings.py
LOGOUT_REDIRECT_URL = 'login'
Template is not place to do redirects on
Use login_required decorator on view instead
redirect doesn't work within the Django template. To redirect you can try some of the decorators that Django has provided us.
Just in your view.py do as I did.
from django.contrib.auth.decorators import login_required
#login_required
def dashboard(request):
return render(request, 'dashboard.html')
In this example, the #login_required decorator checks if the user has logged in. If not, it will redirect the user to the route specified in the LOGOUT_REDIRECT_URL.
Otherwise, if you wish to do this check in the template, you can try some thing like this.
{% if user.is_authenticated %}
<p>Authenticated user</p>
{% else %}
<p>Create a view here which tells the user to login. </p>
{% endif %}
user = authenticate(username='john', password='secret')
if user is not None:
# A backend authenticated the credentials
else:
# No backend authenticated the credentials

How to customize ckan header site navigation tabs

I would like to add extra header site navigation tabs to the default ones.
I have tried working with the solution given here but it is not working for me. I am getting Exception: menu itemapicannot be found error
This is my plugin.py code
import ckan.plugins as plugins
import ckan.plugins.toolkit as toolkit
class ApiPlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm):
plugins.implements(plugins.IRoutes, inherit=True)
def before_map(self, m):
m.connect('api', #name of path route
'/api', #url to map path to
controller='ckanext.kimetrica_theme.controller:ApiController', #controller
action='api') #controller action (method)
return m
This is my header.html code
{% ckan_extends %}
{% block header_site_navigation_tabs %}
{{ h.build_nav_main(
('search', _('Datasets')),
('organizations_index', _('Organizations')),
('group_index', _('Groups')),
('about', _('About')),
('api', _('api'))
) }}
{% endblock %}
And this is my controller.py code
import ckan.plugins as p
from ckan.lib.base import BaseController
class ApiController(BaseController):
def api(self):
return p.toolkit.render('api.html')
I expect to have the api menu work like the rest of the menu do. I also have my template(api.html) in place
Based on what you posted it looks like you haven't setup plugins.implements(plugins.IConfigurer, inherit=True) to register your new template. Try referencing this extension as an example. https://github.com/ckan/ckan/blob/2.8/ckanext/stats/plugin.py for setting up a new page.
You're on the right track for the menu.
Also what version of CKAN are you using? You may want to pswitch this to a flask blueprint. Like this https://github.com/ckan/ckan/blob/2.8/ckanext/example_flask_iblueprint/plugin.py
If you are using 2.9 (in alphha) check this issue out and the comments ckan 2.9.0 iroute before_map not invoking custom controller
I solved this question by using ckanext-pages extension This extension allows you to add simple static pages and blogs and edit their contents.
I solved it by creating a new HTML file for the header, e.g. header_foo.html. Additionally, you have to change the page.html:
…
{%- block header %}
{% include "header_foo.html" %}
{% endblock -%}
…
In the same way, you can hide the navigation tabs.

CSRF error django 1.8 i18n internationalization

Hi I have django internationalization working on my django site. That is if i browse ".../en/foo/bar" and ".../nb/foo/bar" they work fine. But i am trying to get a drop down menu to automatically change the language but i get csrf error.
base.html
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}"/>
<select name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"
{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input type="submit" value="Go"/>
</form>
I however have another form in the same html but I do not but {% csrf_token %} in it. I rather place#csrf_exempt` on the view that handles the form.
I dont know whether having both froms on on html is what is causing the problem.
So what id did was that i created my own set_language view just like in django.veiws.i18n and places the #csrf_exempt on it.
#csrf_exempt
def set_language(request):
"""
Redirect to a given url while setting the chosen language in the
session or cookie. The url and the language code need to be
specified in the request parameters.
Since this view changes how the user will see the rest of the site, it must
only be accessed as a POST request. If called as a GET request, it will
redirect to the page in the request (the 'next' parameter) without changing
any state.
"""
print 'I am in setlang'
next = request.POST.get('next', request.GET.get('next'))
if not is_safe_url(url=next, host=request.get_host()):
print 'not safe'
next = request.META.get('HTTP_REFERER')
if not is_safe_url(url=next, host=request.get_host()):
next = '/'
response = http.HttpResponseRedirect(next)
if request.method == 'POST':
lang_code = request.POST.get('language', None)
if lang_code and check_for_language(lang_code):
if hasattr(request, 'session'):
request.session[LANGUAGE_SESSION_KEY] = lang_code
else:
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code,
max_age=settings.LANGUAGE_COOKIE_AGE,
path=settings.LANGUAGE_COOKIE_PATH,
domain=settings.LANGUAGE_COOKIE_DOMAIN)
return response
Though the CSRF validation error is solved the form has no effect when i change the language and submit. it just stays on the same page. it appears that if not is_safe_url(url=next, host=request.get_host()) is always true. I am not sure what i am doing wrong now
I just realised that my form sends a GET request to the view instead of a post so request.method is GET how and why is this so? The form data does not get to the view at all in this case but they submit when i leave the action attribute of the form blank. The the form submits to the view that called the page. Submitting to a specific view is not working as the request somehow becomes a get request
With first problem - csrf error, there is no simple solution (if you want csrf working, not bypassed) because we can't tell what is happening here - maybe some cookie-related issue.
But second problem is simple to solve. There is bug in django. In simple words, django won't translate url (change prefix in front of URL or translate whole URL) when user is changing language, so user will be redirected to old, not translated URL with old language prefix. That will cause to switch back to old language after redirection.
Solution to that problem is already submitted to django and will be available in django 1.9, but you can get code of that view from github and put it instead of your current language switching view.
Here is full commit for that fix, there is new function called translate_url in urlresolvers that is used in fixed view.

Jekyll - Next and previous links with different categories

I am using Jekyll to build a blog, I managed to successfully implement a Next and Previous links on my layouts pages (using this answer). I've added several categories (using this answer) and each page iterates through the proper categories displaying only what I want them to.
My only problem now is that Previous and Next buttons still iterate through all the posts regardless of what category they are in.
This is the code I used for the Next and Previous links on the bottom of the layout:
{% if page.previous %}
<span class="previous-link">
<a rel="prev" href="{{ page.previous.url }}">Previous Entry</a>
</span>
{% endif %}
{% if page.next %}
<span class="next-link">
<a rel="next" href="{{ page.next.url }}">Next Entry</a>
</span>
{% endif %}
Is there a way to make the Next and Previous buttons go to the next or previous post in the current posts' category?
After a bit of research. I found exactly what I was looking for on this blogpost - http://ajclarkson.co.uk/blog/jekyll-category-post-navigation/
Just needed to add a plugin to the _plugin directory and add this bit of code in it:
module Jekyll
class WithinCategoryPostNavigation < Generator
def generate(site)
site.categories.each_pair do |category, posts|
posts.sort! { |a,b| b <=> a}
posts.each do |post|
index = posts.index post
next_in_category = nil
previous_in_category = nil
if index
if index < posts.length - 1
next_in_category = posts[index + 1]
end
if index > 0
previous_in_category = posts[index - 1]
end
end
post.data["next_in_category"] = next_in_category unless next_in_category.nil?
post.data["previous_in_category"] = previous_in_category unless previous_in_category.nil?
end
end
end
end
end
And instead of using page.next.url and page.prev.url in the HTML, just use page.next_in_category.url and page.previous_in_category.url.
I hope this helps anyone experiencing the same issue.
The ajclarkson plugin for pagination within categories is a correct and useful solution if you are able to install plugins.
If you want to deploy to Github pages, you cannot use plugins.
I use this method to paginate within categories. This makes sure that a post from a different category will never show up:
{% if page.next and page.next.categories contains "blog" %}
Next Post
{% else if page.previous and page.previous.categories contains "blog" %}
Previous Post
{% endif %}
Be aware, this solution will not find a next post if it would have to skip over something from a different category. It avoids the worst (?) scenario, which is linking to something unintentional/not-really-a-post.

Django more than one ListView to an html page

I am looking to be able to access both post_list10, and photo_list on my blog.html however I am only able to access one when it is written like this. Does anyone know how to write it so I can access both?
post_list10 = Post.objects.all().order_by("-date")[:10]
photo_list = Photo.objects.all()
urlpatterns = patterns('',
url(r'^$', ListView.as_view(
queryset=post_list10,
template_name="blog.html")),
# FOR SOME REASON WHICHEVER COMES FIRST TAKES PRECEDENT. Cannot do both.
url(r'^$', ListView.as_view(
queryset=photo_list,
template_name="blog.html")))
Also,
when calling the list in my blog.html I can use
{% for post in object_list %}
.....
{% endfor %}
in order to work with the available post objects but how do I know if I'm working with posts or photos if I can access both? Sorry if my wording is unclear, I'm quite new to this.
The way to solve your problem would usually involve writing your own view.
A simple way of doing this is as follows:
in urls.py:
from views import my_view
urlpatterns = patterns('',
url(r'^$', my_view, name="my_blog"),
)
in views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.template import RequestContext, loader
def my_view(request):
"""The view for your blog page"""
post_list10 = Post.objects.all().order_by("-date")[:10]
photo_list = Photo.objects.all()
template = loader.get_template('blog.html')
context = RequestContext(request,{
'post_list': post_list10,
'photo_list': photo_list,
})
return HttpResponse(template.render(context))
The the template in blog.html would be changed to this:
{% for post in post_list %}
.....
{% endfor %}
{% for photo in photo_list %}
.....
{% endfor %}
Another thing I noticed is this comment "# FOR SOME REASON WHICHEVER COMES FIRST TAKES PRECEDENT. Cannot do both.". This is indeed the correct, and desired, behavior. The way the URL matching works is that Django starts at the top of the of the URL patterns and then iterates through. The first regex match that is found for the URL in the request is the one that is used and no further searching takes place. Because you had the same regex ^$ for both only the first one in the urlpatterns would ever be matched. This behavior will happen every time you have a duplicated regex, the second one just never gets used.
Generally speaking the Django documentation is very high quality, so do read that if you get stuck.