So I am currently working on a project and the client has asked for this requirement.
Basically, I have to provide some sort of mechanism in the admin panel so that the admin can order the navbar items.
Current nav bar
Like in the image above, admin should be able to set the order to eg. SIGN-IN SIGN-UP ABOUT HOME
I'm new to Django but have decent programming skill. Can anyone point me in the right direction?
You will have to make the navbar display data-driven.
Create a model for the navbar display.
from django.db import models
class Navbar(models.Model):
name = models.CharField(max_length=100)
display_order = models.IntegerField(null=True, blank=True)
Register the model so the user can modify in the admin.
from django.contrib import admin
from .models import Navbar
admin.site.register(Navbar)
Create objects for the model class for each of the desired navbar links.
Use content_processors to pass the navbar object to the template that contains the navbar (generally base.html). This link explains in detail how to use content processors.
How can i pass data to django layouts (like 'base.html') without having to provide it through every view?
Your function in content_processors.py should be similar to this.
from .models import Navbar
def add_navbar_data_to_base(request):
return {
'navbar': Navbar.objects.all().order_by('display_order')
}
Now you can add the links to base.html template using a for loop and they will display in the order specified by the display_order which can be modified in the admin.
#base.html
<!DOCTYPE html>
{% load static %}
<html>
<head>
</head>
<body>
{% block nav %}
<nav class="navbar sticky-top navbar-expand navbar-light">
<ul class="navbar-nav">
{% for link in navbar %}
<li class="nav-item">
<a class="nav-link">{{ link }}</a>
</li>
{% endfor %}
</ul>
</nav>
{% endblock %}
{% block content %}
{% endblock %}
</body>
</html>
This code has not been tested but the general idea should work.
Related
I am currently working on django , Need some help how to achive my below goal
I need to publish the latest data and list data in a web app .
Below is the set of steps i followed
Created the Model.py
import datetime
from statistics import mode
from django.db import models
Create your models here.
class documents(models.Model):
author= models.CharField(max_length=30)
title=models.CharField(max_length=50)
description=models.TextField()
creation_date=models.DateTimeField()
update_date=models.DateTimeField()
View.py
from django.shortcuts import render
from django.views.generic.list import ListView
from .models import documents
# Create your views here.
class documentlist(ListView):
template_name='app/document_list.html'
model=documents
context_object_name='document'
HTML snippet
{% extends 'base.html' %}
{% block title %} MY HOMEPAGE {% endblock %}
{% block css %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
{% endblock %}
{% block content %}
<nav class=" navbar navbar-dark bg-primary">
<a class="navbar-brand mb-0 h1" href="#">MEDICARE</a>
</nav>
{% for d in document %}
<td>{{d.title}}</td>
{% endfor %}
{% endblock %}
How can we render both latest data and list of data from a model class in django?I am clear about rendering the list data using listview . can someone help in understanding how to display the latest data from the list to the listview.html
Thanks,Sid
I have figured out the issue and this helped me resolve the issue.
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['latest_post'] = documents.objects.latest('update_date')
return context
Thanks,
SIdh
Well you would go about getting your recent publish data in your listview like this:
class documentlist(ListView):
template_name='app/document_list.html'
model=documents
context_object_name='document'
def get_queryset(self):
return documents.objects.filter(author=request.user).order_by('creation_date')
in your html template you can do something like this to render the latest post
% extends 'base.html' %}
{% block title %} MY HOMEPAGE {% endblock %}
{% block css %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
{% endblock %}
{% block content %}
<nav class=" navbar navbar-dark bg-primary">
<a class="navbar-brand mb-0 h1" href="#">MEDICARE</a>
</nav>
{% for doc in document %}
<td>{{doc.title}}</td>
{% endfor %}
{% endblock %}
Just add ordering by id in descending order:
class documentlist(ListView):
template_name='app/document_list.html'
model=documents
context_object_name='document'
ordering = ['-id']
I know that this post is old enough but not closed yet, it may be useful for someone else.
But i need to show the latest data as the latest post and show as a
fetured one , i have attached screenshot as per my requirement
Facing this equation this is how I did:
My view:
And this is my template
I created a watered down project based of my more complex project for this question to help deliver my question more effectively. I'll include the code below for future viewers of this post but for ease/convenience here is the gitlab repository url.
I have a model "NotesModel" that models the architecture of a note that you might take during the day. It's quite simple there's a 'title', 'tag' and of course the main part which I call the 'content'. The tag is like a tag you link to your stack overflow post. It's just to help identify the topic that a particular note might be about.
In my function based view I query every row in my database and hand it off to my render(.., .., {'notes': notes}) function as you'll see below. With some html/bootstrap styling I display every item from the 'tag' column in my database as a label which is linkable with the ...a href=""... syntax as such.
{% for note in notes %}
<span class="label label-primary" id="tags">
<a id="theurl" href="this is where my confusion is">
{{note.tag}}
</a>
</span>
{% endfor %}
I entered some basic notes already and taken a screen-shot to help show you what my page looks like in hope that it better explains the behavior I want which I explain next.
Screen-shot
The behavior that I want is to treat this label as a actual tag you might find on some forum website. The behavior is as follows...
1) The user clicks on the label
2) Django directs the user to another page
3) The rows in the database that the attribute 'tag' (being the column) matches the name of the label will be displayed.
Let me explain a bit more. From the picture above you can see there are already four notes (being four rows in database terminology) entered into the database. Therefore, the 'tag' attribute (being the 'tag' column in database terminology) has four instances being starwars, startrek, avp, and another starwars instance. I want to be able to click on the tag starwars and it directs me to another page that displays all notes with the 'tag' starwars. Same goes for the other tags. If I click on startrek then I want this to direct me to another page that displays all notes with the 'tag' startrek.
I did at one point try creating another page in my templates folder and then used a query set filter like the following that I passed off to the template.
queryset = NotesModel.objects.filter(tag__icontains='starwars')
Then I just typed the direct link to that page in the ...a href=""... piece of code. However, there's two problems with this solution...
1 It only works for starwars
2 If i did it this way I would have to create x number of page.html files in my templates folder with an equal amount of x number of function based views with the above queryset. This is more static and not a dynamic way of doing things so how do I achieve such a task?
The following are files in my project as of now. As I said earlier i'm including the gitlab repository url above should you want to pull the project down yourself.
the_app/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
]
the_app/models.py
from django.db import models
class NotesModel(models.Model):
title = models.CharField(max_length=100, blank=True)
tag = models.CharField(max_length=100, blank=False)
content = models.CharField(max_length=1000, blank=False)
def __str__(self):
return self.title
the_app/forms.py
from django import forms
from .models import NotesModel
class NotesForm(forms.ModelForm):
class Meta:
model = NotesModel
fields = ['title', 'tag', 'content']
the_app/views.py
from django.shortcuts import render
from .models import NotesModel
from .forms import NotesForm
def home(request):
# Grab the form data
if request.method == 'POST':
form = NotesForm(request.POST)
if form.is_valid():
form.save()
form = NotesForm()
else:
form = NotesForm()
# Grab the data from the database
notes = NotesModel.objects.all()
return render(request, 'the_app/page_home.html', {'form': form, 'notes': notes})
the_app/templates/the_app/base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="{% static 'mystyle.css' %}">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div>
{% block notesform %}{% endblock notesform %}
</div>
<div>
{% block notetags %}{% endblock notetags %}
</div>
</body>
</html>
the_app/templates/the_app/page_home.html
{% extends "the_app/base.html" %}
{% block notesform %}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% endblock notesform %}
{% block notetags %}
{% for note in notes %}
<span class="label label-primary" id="tags">
<!-- I didn't know what to put here so i used google's url as a place holder-->
<a id="theurl" href="https://www.google.com">
{{note.tag}}
</a>
</span>
{% endfor %}
{% endblock notetags %}
Here is the problem, queryset = NotesModel.objects.filter(tag__icontains='starwars') your tag is only containing starwars. So it will not find other tags.
class TagPostView(ListView):
model = NoteModel
template_name = '....'
context_object_name = 'all_notes_of_this_tag'
def get_queryset(self):
result = super(PostTagView, self).get_queryset()
query = self.request.GET.get('q')
if query:
postresult = NoteModel.objects.filter(tag__icontains=query)
result = postresult
else:
result = None
return result
Now you can pass label as q and it will search for that tag and show the result. All you need is only one template for this.
In template you can use,
{% for note in all_notes_of_this_tag %}
{{note.title}}
#..
{% endfor %}
This will solve all three requirements.
I have a number of templates that extend base.html. I want the base.html template to house my global navigation and have the text and links in the global navigation be based on a model Division (i.e. the CharField in the model will be used as the button text in the global nav, and the id will be used to build the URL). I thought tags might work, but what I end up with is this (yes, I'm new to Django and Python):
current_tags.py
from django import template
# Import your model
from libs.display.models import Division
from django.db import models
register = template.Library()
#register.simple_tag
def do_get_divisions(self):
d = Division.objects.all()
mylist = []
for each in d:
mylist.append(str(each.DivisionValue))
return my list
I'm attempting just getting the text value in each object to print at this point because I can't get or work with the objects in the template, as you'll see below.
base.html
<!DOCTYPE html>
<html>
<head>
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}style.css" />
</head>
<body>
{% load current_tags %}
<p>{% do_get_divisions "" %}</p> **THIS ACTUALLY PRINTS mylist**
{% for each in do_get_divisions %} **THIS DOESN'T PRINT ANYTHING**
<p>{{ each }}</p>
{% endfor %}
{% block content %}
{% endblock %}
</body>
</html>
I'm sure there is a better way to do global nav based on a model in Django. I basically want to get all the Division objects and put them into a <ul> to use as my global nav in base.html. I am not that familiar with Django, but my views.py don't help me because I am rendering other templates, not base.html, which are extending base.html. For what it's worth, here's one views.py, where /display/info.html template extends base.html:
# Create your views here.
from django.http import HttpResponse
from apps.pulldata.models import Data
from django.shortcuts import render, get_object_or_404
from django.http import Http404
def info(request, group_id):
group = get_object_or_404(Data, pk=group_id)
s = group.XInGroup.all()
return render(request, 'display/info.html', {'Group': group, 's': s})
You cannot put a templatetag into another. Your for-loop is a templatetag that expects the name of an element in your context to iterate over.
If you want to handle the navigation in a template tag you should consider using inclusion tags.
Inclusion tags are functions that use templates to render their data.
A very basic implementation could look something like this:
tags.py
#register.inclusion_tag('navigation.html')
def navigation(selected_id=None):
return {
'navigation': Division.objects.all(),
'selected':selected_id,
}
In your templatetag file you create a dictionary with the navigation items and optionally the currentl selected item to highlight this navigation element.
navigation.html
<ul>
{% for item in navigation %}
<li{% if item.id == selected %} class="selected"{% endif %}>
{{ item.DivisionValue }}
</li>
{% endfor %}
</ul>
the navigation.html uses the dictionary from the python function as context so you start with simply iterating over the navigation.
base.html
{% navigation %}
or
{% navigation current_division.id %}
In the base.html you call the inclusion tag like a normal template tag. if you want to highlight the current item you add its id as a argument.
I'm building a website using django with a header on top of every page, which basically is a menu with a few links, constant throughout the pages.
However, depending on the page you're on I'd like to highlight the corresponding link on the menu by adding the class "active". To do so, I am currently doing as follow: each page has a full menu block that integrates within a general layout, which does NOT contain the menu. For exemple, page2 would look like this:
{% extends "layout.html" %}
{% block menu %}
<li>Home</li>
<li>page1</li>
<li class="active">page2</li>
<li>page3</li>
{% endblock %}
The problem is that, beside from that solution being not so pretty, every time I want to add a link to the header menu I have to modify each and every page I have. Since this is far from optimal, I was wondering if any of you would know about a better way of doing so.
Thanks in advance!
You can create a custom templatetag:
from django import template
from django.core.urlresolvers import reverse, NoReverseMatch, resolve
register = template.Library()
#register.simple_tag
def active(request, view_name):
url = resolve(request.path)
if url.view_name == view_name:
return 'active'
try:
uri = reverse(view_name)
except NoReverseMatch:
uri = view_name
if request.path.startswith(uri):
return 'active'
return ''
And use it in the template to recognize which page is loaded by URL
<li class="{% active request 'car_edit' %}">Edit</li>
If you have a "page" object at every view, you could compare a navigation item's slug to the object's slug
navigation.html
<ul>
{% for page in navigation %}
<li{% ifequal object.slug page.slug %} class="active"{% endifequal %}>
{{ page.title }}
</li>
{% endfor %}
</ul>
base.html
<html>
<head />
<body>
{% include "navigation.html" %}
{% block content %}
Welcome Earthling.
{% endblock %}
</body>
</html>
page.html
{% extends "base.html" %}
{% block content %}
{{ object }}
{% endblock %}
Where navigation is perhaps a context_processor variable holding all the pages, and object is the current PageDetailView object variable
Disclaimer
There are many solutions for your problem as noted by Paulo. Of course this solution assumes that every view holds a page object, a concept usually implemented by a CMS. If you have views that do not derive from the Page app you would have to inject page pretenders within the navigation (atleast holding a get_absolute_url and title attribute).
This might be a very nice learning experience, but you'll probably save loads time installing feinCMS or django-cms which both define an ApplicationContent principle also.
You may use the include tag and pass it a value which is the current page.
For example, this may be a separate file for declaring the menu template only:
menu.html
{% if active = "a" %}
<li>Home</li>
{% if active = "b" %}
<li>page1</li>
{% if active = "c" %}
<li class="active">page2</li>
{% if active = "d" %}
<li>page3</li>
And call this from within your template like this:
{% include 'path/to/menu.html' with active="b"%} # or a or c or d.
Hope it helps!
I have my photos located on Flickr. I want to sync them between Flickr and my Django app using django-syncr. It's installed, Flickr section is visible in Admin site. I can sync photo data from Flickr to my local database. In a few words -- it works.
But, I don't understand how to get these data from my database using views.py and template file?I mean, how to make my Flickr's photos visible on my site?
I got something like this on my site:
* IMG_2467
* Morning fog on Halong bay
I used these files but get only title from all data and didn't anything else, including photos.
views.py
from django.shortcuts import render_to_response
from syncr.flickr.models import Photo
def index(request):
get_photo = Photo.objects.all()
return render_to_response('index.html', {'get_photo': get_photo})
index.html
<html>
<title>
Test page
</title>
<body>
{% if get_photo %}
<ul>
{% for photo in get_photo %}
<li>{{ photo }}</li>
{% endfor %}
</ul>
{% else %}
<p>No photos are available.</p>
{% endif %}
</body>
</html>
maybe you should add <img src='{{photo.url}}' /> ? I don't see how do you plan to show images if you're just importing the names.