I'm trying to open a specific bootstrap tab on a webpage using page slugs. For example:
www.mysite.domain/profile/#my_courses
will open profile page with courses history tab active
Here is my code:
urls.py
urlpatterns = [
url(r'^profile/$', views.profile, name='profile'),
url(r'^profile/(?P<page_slug>[\w-]+)/$', views.profile, name='profile'),
]
view.py profile
#login_required
def profile(request, page_slug=None):
profile = UserProfile.objects.get(user__username=request.user.username)
courses = Course.objects.filter(trainer__in = [profile]).order_by('start_time')
trainings = Course.objects.filter(students__in = [profile]).order_by('start_time')
return render(request, 'accounts/profile.html', context = {'courses': courses,
'trainings': trainings,
'page_slug': page_slug,})
profile.html
{% extends 'base.html' %}
{% load staticfiles %}
{% load i18n %}
{% block headers %}
{{ block.super }}
<link rel='stylesheet' href='{% static "accounts/css/profile.css" %}'/>
{% endblock %}
{% block content %}
<ul class='nav nav-tabs navbar-inverse'>
<li class='active'><a href= '#profile' data-toggle='tab'>{% trans 'Profile' %}</a></li>
<li><a href='#trainings' data-toggle='tab'>{% trans 'My Trainings' %}</a></li>
{% if user.profile.is_trainer %}
<li><a href='#courses' data-toggle='tab'>{% trans 'My Courses' %}</a></li>
{% endif %}
</ul>
<div id='content' class='tab-content'>
<div class='tab-pane fade active in' id='profile'></div>
<div class='tab-pane fade' id='my_trainings'>
<ul class='courses__container'></ul>
</div>
{% if user.profile.is_trainer %}
<div class='tab-pane fade' id='courses'>
<ul class='courses__container'></ul>
</div>
{% endif %}
</div>
{% endblock %}
Since javascript on user-side can't understand django template tags I can't do this in javascript. How can I add/remove active class in <li> and <div> tags in django template?
In the URL
www.mysite.domain/profile/#my_courses
#my_courses is a fragment, not a slug. URL fragments only exist in the browser, they are not sent to the web server, and so you URL routing and templates will never see them.
When the user visits that url, what is sent to the server is
www.mysite.domain/profile/
And that's the page that is returned. You'd need JavaScript on the page to inspect the full URL (through document.location.href) and update the page accordingly.
A slug, on the other hand, is not separated by a # character, and forms part of the URL that is sent to the server. That can be seen by Django, and inform the view as to what to render in the template. You would need to redesign your URLs to take advantage of that, though.
Related
I have this small blog post app where everything works fine apart from delete view. As soon as I hit delete button I'm moved to my delete post page but when I hit confirm from DeleteView html page I get 405 error
My views.py for delete looks like this:
class DeletePost(DetailView):
model = Articles
template_name = 'delete_article.html'
success_url = reverse_lazy('list_articles')
My html file where the link is mentioned is like this:
<!DOCTYPE html>
{% extends 'base.html' %}
{% block body %}
<div class="container">
{% for i in articles %}
<div class="jumbotron">
<h2>{{i.title}}</h2>
<p>- {{i.author}}</p>
{{i.created_on}}
{{i.updated_on}}
<p>{{i.content}}</p>
<a class="btn btn-warning" href="{% url 'update_article' i.id %}">Update</a>
<a class="btn btn-danger" href="{% url 'delete_article' i.id %}">Delete</a>
</div>
{% endfor %}
</div>
{% endblock %}
urls.py looks this way:
from django.urls import path
from mysite import views
urlpatterns = [
path('articles/', views.PostList.as_view(), name='list_articles'),
path('articles/<pk>/', views.PostDetail.as_view(), name='detail_article'),
path('create/new/', views.CreateNewPost.as_view(), name='create_new_article'),
path('update/<pk>/', views.UpdatePost.as_view(), name='update_article'),
path('delete/<pk>/', views.DeletePost.as_view(), name='delete_article'),
]
and html for DeleteView:
<!DOCTYPE html>
{% extends 'base.html' %}
{% block body %}
<form method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
{{ form.as_p }}
<input class='btn btn-danger' type="submit" value="Confirm">
</form>
{% endblock %}
You have mentioned DetailView for deletion which is not correct, mention DeleteView instead which is at from django.views.generic.edit import DeleteView.
Note: Class based views required actual view name as the suffix, so you should write it as PostDeleteView instead of DeletePost. Similarly, write PostListView, PostDetailView etc. Add model name as the prefix and view name as the suffix and must be in PascalCase.
405 means method not allowed, change your form POST method to DELETE method.
<form method="DELETE">
I have previously been using path("", include(wagtail_urls)) for my home_page url which displays the template at home/home_page.html correctly
I wish to however display different pages depending on whether a user is logged in or not so have changed this to:
def logged_in_switch_view(logged_in_view, logged_out_view):
'''switches views dependedn on logon status'''
def inner_view(request, *args, **kwargs):
if request.user.is_authenticated:
return logged_in_view(request, *args, **kwargs)
return logged_out_view(request, *args, **kwargs)
return inner_view
urlpatterns = [
path("",
logged_in_switch_view(
TemplateView.as_view(template_name="home/home_page.html")),
TemplateView.as_view(template_name="home/not_authenticated.html")),
name="home"),
]
With this approach (directly specifying the template rather than using wagtail_urls) the home page does not display correctly when logged in, in that all the wagtail tags in the html e.g. the blog posts are not displaying
home_page.html
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}
{% block content %}
<main class="container">
{% for post in page.blogs %}
{% with post=post.specific %}
<div class="col-md-8 mx-auto px-auto">
<div class="row border rounded overflow-auto flex-md-row mb-4 shadow-sm position-relative ">
<div class="col p-4 d-flex flex-column position-static">
<strong class="d-inline-block mb-2 text-primary">{{ post.category }}</strong>
<div class="mb-1 text-muted">{{ post.date }}</div>
<h3 class="mb-0">{{ post.title }}</h3>
<p>{{post.intro}}</p>
</div>
<div class="col-auto my-auto py-2 px-2 d-none d-lg-block">
<a href="{% pageurl post %}" class="stretched-link">
{% with post.main_image as main_image %}{% if main_image %}
{% image main_image min-250x250 max-350x350%}
{% endif %}{% endwith %}
</a>
</div>
</div>
</div>
{% endwith %}
{% endfor %}
</main>
{% endblock %}
How should I specify the home_page in the logged_in_switch_view function?
The include(wagtail_urls) pulls in Wagtail's page handling logic for selecting which page should be returned for a given URL. If you swap that line out with your own code, you're effectively swapping out all of Wagtail...
First, consider whether you're reinventing the page privacy feature that Wagtail already provides. If you want the site as a whole to require a login, and non-logged-in users to be given a blanket generic login form, you can enable this using the Privacy control under the Settings tab (or in the top right corner on older Wagtail releases) when editing the homepage, and set WAGTAIL_FRONTEND_LOGIN_TEMPLATE = "home/not_authenticated.html" in your project settings file.
If you just want to swap the template for the homepage specifically, you can do that by defining a get_template method on your HomePage model:
class HomePage(Page):
# ...
def get_template(self, request, *args, **kwargs):
if request.user.is_authenticated:
return "home/home_page.html"
else:
return "home/not_authenticated.html"
This way, your homepage will select one template or the other, but still keep the page object available on the template.
I'm trying to figure out a way to build a list of URLs for my content in my django app. I have the Models and Views setup properly, and I already figured out how to access this data in the Templates, but I'm not quite sure how I can start making URLs for them.
The data I have is continents and the countries of these continents. The template should render a list of the continents, but as links.
Here's an example with one continent:
<ul id="continentMenu">
<li>Scandinavia</li>
</ul>
My urls.py looks like
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('countrydata.urls')),
url(r'^', include('selectui.urls')),
]
and my index.html looks like
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
{% if user.is_authenticated %}
Hi {{ user.username }}!
<p>logout</p>
{% else %}
<p>You are not logged in</p>
login
{% endif %}
{% endblock %}
My continentmenu.html, which I'm trying to have the links for the continents in, looks like
{% extends "base.html" %}
{% load staticfiles %}
{% block content %}
<div class="container-fluid">
<div class="l">
{% for continent in all_continents %}
<h1> {{ continent.name }}</h1>
<p> {{ continent.code }}</p>
{% for country in continent.countries.all %}
<p> {{country.name}}</p>
{% endfor %}
{% endfor %}
</div>
</div>
{% endblock %}
At the moment, but I only made it print all the continents and countries as plain text to make sure that I was successfully parsing through the objects (which I was). I'm having trouble at figuring out what kind of instructions I need to put into {% url %}, as my first attempts lead to nothing but errors.
The ajax.js I've been given to work with looks like
/* Run once document ready. */
$(function() {
"use strict";
#continentMenu.
$("#continentMenu a").on("click", function(event) {
event.preventDefault();
var url = $(this).attr("href");
$("#continentName").text($(this).text());
$("#tableContainer").load(url);
});
});
and the views.py looks like
from django.shortcuts import render, get_object_or_404
from countrydata.models import Continent
def show_continent(request, continent_code=None):
context = {
"all_continents": Continent.objects.all()
}
if continent_code:
continent = get_object_or_404(Continent, code=continent_code)
context["continent"] = continent
return render(request, "selectui/index.html", context)
I have a ListView Template in Django 1.11 that renders to group_list.html. However I want the same view to show in a column in the home page
I also have screenshots below if that helps understanding what I am trying to achieve
I have tried different ways to use {% include 'some.html' %}
1) I tried to make a html page and include it in homepage. but it keeps giving errors
2) I tried to change the group_list.html page into a (insert template) that and tried to insert that, in both the index page and created another template view for groups. but that is giving errors too
Below are my views and templates
Views.py
class GroupCreate(LoginRequiredMixin, CreateView):
model = Group
fields = ('name', 'description')
class GroupList(ListView):
model = Group
class GroupDetail(DetailView):
model = Group
Below is my Index.html and group_list.html
INDEX.HTML
{% extends 'base.html' %}
{% block body %}
<div class="col-md-8" style="background-color:white; border-right:1px solid grey;">
<h4>Groups</h4>
<p>Join a group or make a new Group.</p>
<a style="float:left" class="btn btn-success" href="{% url 'groups:new' %}">Start a Group</a>
<div class="content">
<!--{ % include 'groups/some.html' % } I am trying to insert my -->
</div>
</div>
<div class="col-md-4" style=background-color:white">
<h4>Second Coloumn</h4>
</div>
{% endblock %}
Below is my group_list.html
{% extends 'groups/group_base.html' %}
{% block pre_group %}
<div class="col-md-4">
<div>
<h2>Welcome Back
{{group.user.username}}
</h2>
<h3>Groups</h3>
<p>Welcome to the groups page! Select the Group with the shared interest</p>
</div>
<div>
{% if user.is_authenticated %}
<a class="btn btn-warning" href="{% url 'groups:new' %}"><span class="glyphicon glyphicon-plus-sign"></span> Create a New Group</a>
{% endif %}
</div>
</div>
{% endblock %}
{% block content %}
<div class="col-md-8">
<div class="list-group">
{% for group in object_list %}
<a class="list-group-item" href="{% url 'groups:single' slug=group.slug %}">
<h3 class="list-group-item-heading">{{group.name}}</h3>
<div class="list-group-item-text container-fluid">
{{group.description_html|safe}}
<div class="row">
<div class="col-md-4">
<span class="badge">{{group.members.count}}</span> member{{group.members.count|pluralize}}
</div>
<div class="col-md-4">
<span class="badge">{{group.posts.count}}</span> post{{group.posts.count|pluralize}}
</div>
</div>
</div>
</a>
{% endfor %}
</div>
</div>
{% endblock %}
The HomePage View comes from the root Views they are below
View.py(root directory)
from django.views.generic import TemplateView
class Homepage(TemplateView):
template_name = 'index.html'
class LoggedIn(TemplateView):
template_name = 'test.html'
class LoggedOut(TemplateView):
template_name = 'thanks.html'
I am still learning Django while working on my 1st independent project. I did a some research but could not solve this
I want a list view like this to show on a section of the HomePage
Currently the view works perfectly well on the groups page
In your homepage view you can override get_context_data and add the groups to the context.
class Homepage(TemplateView):
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super(Homepage, self).get_context_data(**kwargs)
context['object_list'] = Group.objects.all()
return context
In the index.html, you'll have to copy the code from your group_list.html template. To prevent duplication, you could move the code from the content block into a include_groups.html template, then use {% include 'include_groups.html' %} in yourindex.htmlandgroup_list.html` templates.
In this case, since your Homepage view is just a template view, you could use a ListView instead.
class Homepage(ListView):
model = Group
template = 'index.html'
Whichever option you go for, it's useful to understand how to override get_context_data in class based views.
I'm spending hours on this thing.
I have a category page, and inside that page there's list of posts that leads to single post page if I click a particular one.
Single post page is working, single category page is working, but a page inside category page is not working, does this make sense?
def post(request, slug):#this is my view
single_post = get_object_or_404(Post, slug=slug)
single_post.views += 1 # increment the number of views
single_post.save() # and save it
t = loader.get_template('main/post.html')
context_dict = {
'single_post': single_post,
}
c = Context(context_dict)
return HttpResponse(t.render(c))
def category(request, category_name_slug):
context_dict = {}
try:
category = Category.objects.get(slug=category_name_slug)
context_dict['category_name'] = category.name
posts = Post.objects.filter(category=category)
context_dict['posts'] = posts
context_dict['category'] = category
except Category.DoesNotExist:
pass
return render(request, 'main/category.html', context_dict)
this is my url
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P<slug>[\w|\-]+)/$', views.post, name='post'),
url(r'^category/(?P<category_name_slug>[\w\-]+)/$', views.category, name='category')
]
And this is my category html
{% extends 'base.html' %}
{% block content %}
<h1>{{category_name}}</h1>
{% if category %}
{%if posts %}
<ul>
{% for post in posts %}
<h3>{{ post.title }}</h3>
{% endfor %}
</ul>
{%else%}
<strong>No Pages </strong>
{% endif %}
{% else %}
{{category_name}} does not exist
{% endif %}
{% endblock %}
Finally post.html
<html>
<head>
<title></title>
<head>
<body>
<h2>{{single_post.title}}</h2>
<p>{{single_post.content}}</p>
<p> Views: {{single_post.views}}
<br>
<p>
{% if single_post.image %}
<img src="/media/{{single_post.image}}">
{% endif %}
</p>
<body>
it gives me 404 error, interesting thing is url that's giving me error is 127.0.0.1:8000/category/hello/adele but 127.0.0.1:8000/adele doesn't give me error. so inside category page, i want the access for 127.0.0.1:8000/adele –
replace {{ post.title }} with {{ post.title }}
The issue is if the reference in anchor doesnt starts with / it means its a relative url and that reference is added to current url. Hope this helps you. Also for further reference please use absolute_url feature of django. Please read this :)
Use the url template tag:
{% for post in posts %}
<h3>{{ post.title }}</h3>
{% endfor %}
This reconstruct the url based on your url configuration, ensuring it is a valid url. Here, 'post' is the name of the url you defined in your urlconf, and slug=post.slug is the parameter you pass to the capturing group in your url regex.