DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

My View File

03.08.2009
| 2773 views |
  • submit to reddit
        ## Author: Mike Lewis
## Date: 02/28/09
## File: /mike/mlewis/views.py
##
## View classes and routing methods.


from django.template.loader import render_to_string
from django.db.models import signals
from django.dispatch import dispatcher
from django.core.paginator import Paginator
from django.http import HttpResponse
from django.core import serializers
from django.utils import simplejson
from django.db.models.query import QuerySet
from mike.mlewis.models import *
import logging


## ROUTING CALLS ##
# These methods route urls in Django's URLConf to the appropriate method in a view class.

def get_next_page(request):
        """Routes pagination calls to the appropriate view class.
            Returns an HttpResponse object with JSON."""

        request_path = request.path
        if request_path.find('tag') != -1:
                return TagView.get_next_page(request)
        elif request_path.find('archive') != -1:
                return ArchiveView.get_next_page(request)
        elif request_path.find('search') != -1:
                return SearchView.get_next_page(request)
        else:
                return BlogView.get_next_page(BlogView(), request)

def index(request):
        """Routes calls to index page to the appropriate view.
            Returns an HttpResponse object with JSON."""

        return View.index(View(), request)

def blog(request):
        """Routes calls to the blog start page to the BlogView and loads the template.
           Returns an HttpResponse with the blog template rendered."""

        return BlogView.blog(BlogView(), request)

def tag(request):
        """Routes calls to the tag method to the TagView.
           Returns an HttpResponse object with JSON."""

        return TagView.tag(TagView(request), request)

def archive(request):
        """Routes calls to the archive method to the ArchiveView.
           Returns an HttpResponse object with JSON."""

        return ArchiveView.archive(ArchiveView(), request)

def search(request):
        """Routes calls to search method to the SearchView.
           Return an HttpResponse object with JSON."""

        return SearchView.search(SearchView(request), request)

def project(request):
        """Routes calls to project start page to ProjectView.
           Returns an HttpResponse object with the project template loaded."""

        return ProjectView.project(ProjectView(), request)

## END ROUTING CALLS ##


## VIEW CLASSES ##

class View(object):
        """Base view class."""

        js_includes = ["/site_media/js/prototype.js", "/site_media/js/scriptaculous.js",
                         "/site_media/js/base.js"]

        css_includes = ["/site_media/css/layout.css", "/site_media/css/lightbox.css"]

        def make_json(self, data):
                """Processes the given data as JSON.
                   Returns JSON."""

                # if we have a dictionary we have to make sure to
                # handle the serialization of QuerySets and lists differently as that's the way
                # django works right now.
                if type(data) is dict:
                        # filter out any QuerySets
                        query_sets = {}
                        for k, v in data.items():

                                # store the QuerySet and replace it with a string in original dict
                                if isinstance(v, QuerySet) or type(v) is list:
                                        query_sets[k] = v
                                        data[k] = '<' + k + '>'

                        # serialize the non-QuerySet data
                        js_data = simplejson.dumps(data, ensure_ascii=False)

                        # replace any place-markers with the appropriate QuerySet serialized in the good way
                        for k, v in query_sets.items():
                                js_data = js_data.replace('"<' + k + '>"', self.make_json(v))

                        return js_data
                else:
                        # not a dict, try to serialize QuerySet
                        try:
                                js_data = serializers.serialize("json", data)
                        except:
                                js_data = simplejson.dumps(data, ensure_ascii=False)

                        return js_data

        def prepareTplParams(self, params, t_params):
                """Prepares template params by mixing the given local params and global params. If a
                   conflict is found between keys in params and t_params the following occurs:
                        1) if value in t_params is a list, then the list is extended with the value(s) in params.
                        2) if value in t_params is NOT a list, the value in params (local) is taken."""

                for k, v in params.items():
                        if k in t_params and type(t_params[k]) is list:
                                t_params[k].extend(params[k])
                        else:
                                t_params[k] = params[k]

                return t_params;

        def load_template(self, name, params):
                """Loads the given template name filling in the given params.
                   Returns an HttpResponse object with the given template rendered in context."""

                links = Link.objects.all()
                tpl_params = {'css_includes': self.css_includes, 'js_includes': self.js_includes,
                              'links': links}

                if len(params) > 0:
                        tpl_params = self.prepareTplParams(params, tpl_params)
                rendered = render_to_string(name, tpl_params)
                return HttpResponse(rendered)

        def index(self, request):
                pod = PicOfDay.pod_objects.get_pic()

                return self.load_template('index.html', {'pod_url': pod.pod_url, 'pod_img': "/site_media/images/" + pod.pod_img})


class BlogView(View):
        """A view class to handle base blog interactions."""

        def __init__(self):
                self.paginator = Paginator(BlogEntry.objects.all(), 4)

        def get_next_page(self, request):
                """Fetches the next page of objects. Depends on self.paginator being set.
                   Returns an HttpResponse object with JSON."""

                page_num = request.POST['page_num']
                ret_vals = {'num_pages': self.paginator.num_pages,
                            'entries': self.paginator.page(page_num).object_list}

                return HttpResponse(super(BlogView, self).make_json(ret_vals))

        def blog(self, request):
                """Loads the blog template with the appropriate data in context.
                   Returns an HttpResponse object with the blog template rendered."""

                entries = self.paginator.page(1).object_list
                entry_years = ArchiveView.get_archive_array(ArchiveView())

                # build the tag cloud by adjusting font sizes on Tag models
                for e in entries:
                        TagView.make_tag_cloud(TagView(request), e)
                        e.tag_array = TagView.get_tag_array(TagView(request), e)
                tag_cloud = Tag.objects.all()

                # determines whether to show pagination liks or not
                if self.paginator.num_pages > 1:
                        paginate = True
                else:
                        paginate = False

                params = {'blogEntries': entries, 'tag_cloud': tag_cloud,
                        'entry_years': entry_years, 'paginate': paginate,
                        'css_includes': ["/site_media/css/blog.css"], 'js_includes': ["/site_media/js/blog.js"]}

                return super(BlogView, self).load_template('blog.html', params)

class TagView(BlogView):
        """View class to handle all tag related actions."""

        def __init__(self, request):
                # prepare the paginator for later requests
                if request.method == 'POST':
                        tag_name = request.POST['tag_name']
                        entries = BlogEntry.entry_objects.get_by_tag_name(tag_name)
                        self.paginator = Paginator(entries, 4)

        def make_tag_cloud(self, entry):
                """ Constructs a tag cloud for blog entries by changing font size.
                    All actions saved in db."""

                e = entry
                tags = e.tags.all()
                for tag in tags:
                        tag.total = tag.blogentry_set.all().count();
                        tag.save()

                tag_list = Tag.objects.all()
                groups = 4
                font_size = 10
                thresholds = []

                min_tag = min(tag_list)
                max_tag = max(tag_list)
                diff = (float(max_tag.total) - float(min_tag.total)) / (float(groups))

                for i in range(groups):
                        thresh = float(min_tag.total) + (i+1) * diff
                        thresholds.append(thresh)

                for tag in tag_list:
                        font = False
                        for group in range(groups):
                                if font == False:
                                        if (tag.total <= thresholds[group]):
                                                tag.size = font_size + group * 2
                                                tag.save()
                                                font = True

        def get_tag_array(self, e):
                """Fetches the list of tags for the given entry.
                   Returns an array of tag names."""
                tags = e.tags.all()
                return [t.tag_name for t in tags]

        def tag(self, request):
                """Fetches the first page of entries by tag name.
                   Return an HttpResponse object with JSON."""

                ret_vals = {'num_pages': self.paginator.num_pages,
                            'entries': self.paginator.page(1).object_list}

                return HttpResponse(super(TagView, self).make_json(ret_vals), mimetype="text/json")

class SearchView(BlogView):
        """View class to handle all search related actions."""

        def __init__(self, request):
                if request.method == 'POST':
                        search_val = request.POST['search_val']
                        self.paginator = Paginator(BlogEntry.entry_objects.search(search_val), 4)

        def search(self, request):
                """Fetches the first page of entries for the search value.
                   Returns an HttpResponse object with JSON."""

                ret_vals = {'num_pages': self.paginator.num_pages,
                            'entries': self.paginator.page(1).object_list}

                return HttpResponse(super(SearchView, self).make_json(ret_vals), mimetype="text/json")

class ArchiveView(BlogView):
        """View class to handle all archive related actions."""

        def get_archive_array(self):
                """Fetches all months containing blog entries by year.
                   Returns a dictionary with months by year."""

                archive_array = {}
                entry_years = BlogEntry.entry_objects.get_entry_years()
                for y in entry_years:
                        archive_array[`y`] = BlogEntry.entry_objects.get_entry_months_by_year(y)

                return archive_array

        def archive(self, request):
                """Fetches the first page of entries for the given month and year.
                   Returns and HttpResponse object with JSON."""

                ret_vals = {'num_pages': self.paginator.num_pages,
                            'entries': self.paginator.page(1).object_list}
                return HttpResponse(super(ArchiveView, self).make_json(ret_vals))

class ProjectView(View):

        def project(self, request):
                projects = Project.objects.all()
                return super(ProjectView, self).load_template('project.html', {'css_includes': ["/site_media/css/project.css"],
                                                                                'projects': projects})