Reputation: 63
How exactly can I customize a generic DetailView in Django. For example in my webapp that show all backups in given root directory together with their size, I mostly use generic views to display the content, but I don't have slightest idea how to deal with the customization. This is Django tutorial - DetailView page.
This is my DetailView:
class ProjectDetailView(LoginRequiredMixin, DetailView):
model = Project
template_name = "projects_portal/details.html"
This is my URL:
url(r'^projects_portal/(?P<pk>\d+)/view/$', ProjectDetailView.as_view(), name="projects_details"),
This is the model:
class Project(models.Model):
root_dir = models.CharField(blank=False, null=False, max_length=2000, verbose_name=_(u"project root directory"))
project_name = models.CharField(blank=False, null=False, max_length=200, verbose_name=_(u"project name"))
total_backups_size = models.IntegerField(blank=True, null=True, verbose_name=_(u"total backups size"))
earliest_backup = models.DateTimeField(blank=True, null=True, verbose_name=_(u"earliest backup"))
latest_backup = models.DateTimeField(blank=True, null=True, verbose_name=_(u"latest backup"))
and this is my .html:
{% extends "projects_portal/base.html" %}
{% block title %}Details{% endblock %}
{% block extracss %}
<style>
div{font-size:24px;}
.col-md-2{width:400px}
</style>
{% endblock extracss %}
{% block content %}
<table class="table table table-hover">
<tr>
<div class="row top-buffer">
<td><div class="col-md-1"><strong>Root directory:</strong></div></td>
<td><div class="col-md-2">{{project.root_dir}}</div></td>
</div>
</tr>
<tr>
<div class="row top-buffer">
<td><div class="col-md-1"><strong>Project name:</strong></div></td>
<td><div class="col-md-2">{{project.project_name}}</div></td>
</div>
</tr>
<tr><td></td><td></td></tr>
</table>
<div class="row">
<div class="col-md-2 col-md-offset-5 text-center">
<td>
<div class="col-md-1 col-md-offset-1 text-center"><a href="{% url 'projects_portal' %}"><button class="btn btn-success btn-lg">OK</button></a></div>
</td>
<td></td>
</div>
</div>
{% endblock %}
The thing is that I want to add some content in the generic detailView so that it must visualize a list of all subfolders in given project and show their size. I prepared two functions to deal with this problem:
def traverse_dir(path):
path_len = len(path)
dir_dict = {}
for dirName, subdirList, fileList in os.walk(path):
dir_size = get_size(dirName)
dir_dict[dirName[path_len:]] = dir_size
return dir_dict
def get_size(start_path = '.'):
total_size = 0
for dirpath, dirnames, filenames in os.walk(start_path):
for f in filenames:
fp = os.path.join(dirpath, f)
total_size += os.path.getsize(fp)
return total_size
The first one traverses the root directory and use the second one to get the size of each directory. The functions are tested and they are OK. The problem is how to implement them in the generic DetailView.
Upvotes: 1
Views: 1781
Reputation: 15114
To add content to your DetailView
override the get_context_data
method. For instance, if you add the following method to your ProjectDetailView
class:
def get_context_data(self, **kwargs):
context = super(ProjectDetailView, self).get_context_data(**kwargs)
context['hello'] = "Hello, world"
return context
you will have an extra context variable named hello
in your template, so you would output it with {{ hello }}
.
Hint: CBV Inspector is your friend when you deal with CBVs.
Update
OP wanted to pass the directory django is running from to his traverse_dir
function. To do that, you can add the following to your settings.py
(django 1.6 adds it by default):
import os BASE_DIR = os.path.dirname(os.path.dirname(__file__))
Now, you can change your get_context_path
method of ProjectDetailView
like this:
from django.conf import settings
def get_context_data(self, **kwargs):
context = super(ProjectDetailView, self).get_context_data(**kwargs)
context['dirs'] = traverse_dir(settings.BASE_PATH)
return context
Now you will have a dirs
variable in your context which can be outputed using (for instance) a {% for %}
loop.
Notice: I haven't checked if traverse_dir
is working as expected.
Update 2
It turns out the OP had a different question: How to display a folder hierarchy with django. What I'd do is create simple view (not DetailView) named traverse
and add the following url patterns in my urls.py
url(r'^traverse/(.+)*', 'views.test.traverse', name='traverse' ),
Now, the traverse
view could be implemented like this:
def traverse(request, segments=""):
segments = segments.split(r'/')
# segments is an array of the url paths
# construct the path of the folder you want to view here
# by concatenate settings.BASE_PATH with the url components
# finally output the contents of the folder by creating links
# which concatenate the segments with the contents of the folder
Upvotes: 2