Ticket #11727: contrib.breadcrumbs.diff

File contrib.breadcrumbs.diff, 10.5 KB (added by chronos, 6 years ago)

The breadcrumbs system.

  • contrib/breadcrumbs/breadcrumbs.py

    diff -urN django-original/contrib/breadcrumbs/breadcrumbs.py django/contrib/breadcrumbs/breadcrumbs.py
    old new  
     1"""
     2Classes to add request.breadcrumbs as one class to have a list of breadcrumbs
     3TODO: maybe is better to move to contrib/breadcrumbs
     4"""
     5
     6from django.conf import settings
     7from django.utils.translation import ugettext_lazy as _
     8from django.utils.safestring import mark_safe
     9from django.utils.text import force_unicode
     10import sys
     11
     12class Singleton(object):
     13    """
     14    We use a simple singleton pattern in Breadcrumbs.
     15    Example from http://svn.ademar.org/code/trunk/junk-code/singleton_vs_borg.py
     16    """
     17    def __new__(cls, *args, **kwds):
     18        it = cls.__dict__.get("__it__")
     19        if it is not None:
     20            return it
     21        cls.__it__ = it = object.__new__(cls)
     22        it._1st_init(*args, **kwds)
     23        return it
     24
     25    def _1st_init(self, *args, **kwds):
     26        pass
     27
     28class BreadcrumbsInvalidFormat(Exception):
     29    """
     30    Simple exception that can be extended
     31    """
     32    pass
     33
     34class BreadcrumbsNotSet(Exception):
     35    """
     36    Raised in utils.breadcrumbs_for_flatpages when we not have breadcrumbs in
     37    request.
     38    """
     39    pass
     40
     41class Breadcrumb(object):
     42    """
     43    Breadcrumb can have methods to customize breadcrumb object, Breadcrumbs
     44    class send to us name and url.
     45    """
     46    def __init__(self,name,url):
     47        # HERE
     48        #
     49        # If I don't use force_unicode, always runs ok, but have problems on
     50        # template with unicode text
     51        self.name = name
     52        self.url = url
     53
     54    def __str__(self):
     55        return self.__unicode__()
     56
     57    def __unicode__(self):
     58        return u"%s,%s" % (self.name,self.url)
     59
     60    def __repr__(self):
     61        return u"Breadcrumb <%s,%s>" % (self.name,self.url)
     62
     63class Breadcrumbs(Singleton):
     64    """
     65    Breadcrumbs maintain a list of breadcrumbs that you can get interating with
     66    class or with get_breadcrumbs().
     67    """
     68    def _1st_init(self,*args,**kwargs):
     69        """
     70        singleton function that start some variables
     71        """
     72        self._clean()
     73        self.__init__(*args,**kwargs)
     74
     75    def __call__(self,*args,**kwargs):
     76        if not len(args) and not len(kwargs):
     77            return self
     78        return self.__init__(*args,**kwargs)
     79
     80    def _clean(self):
     81        self.__bds = []
     82        self.__autohome=settings.BREADCRUMBS_AUTO_HOME
     83        self.__urls =[]
     84
     85    def __init__(self,*args,**kwargs):
     86        """
     87        Call validate and if ok, call fill bd
     88        """
     89        if settings.BREADCRUMBS:
     90
     91            # fill home if settings.BREADCRUMBS_AUTO_HOME is True
     92            if self.__autohome and len(self.__bds) == 0:
     93                self.__fill_bds( ( _("Home"), u"/" ) )
     94
     95            # match Breadcrumbs( 'name', 'url' )
     96            if len(args) == 2 and type(args[0]) not in (list,tuple):
     97                if(self.__validate(args,0)):
     98                    self.__fill_bds( args )
     99            # match ( ( 'name', 'url'), ..) and samething with list
     100            elif len(args) == 1 and type(args[0]) in (list,tuple) \
     101                    and len(args[0]) > 0:
     102                for i,arg in enumerate(args[0]):
     103                    if self.__validate(arg,i):
     104                        self.__fill_bds( arg )
     105            # try to ( obj1, obj2, ... ) and samething with list
     106            else:
     107                for i,arg in enumerate(args):
     108                    if(self.__validate(arg,i)):
     109                        self.__fill_bds( arg )
     110
     111    def __validate(self,obj,index):
     112        """
     113        check for object type and return a string as name for each item of a
     114        list or tuple with items, if error was found raise
     115        BreadcrumbsInvalidFormat
     116        """
     117        # for list or tuple
     118        if type(obj) in (list,tuple):
     119            if len(obj) == 2:
     120                if (not obj[0] and not obj[1]) or \
     121                ( type(obj[0]) not in (str,unicode) and \
     122                  type(obj[1]) not in (str,unicode)):
     123                    raise BreadcrumbsInvalidFormat(u"Invalid format for \
     124                        breadcrumb %s in %s" % (index,type(obj).__name__))
     125            if len(obj) != 2:
     126                raise BreadcrumbsInvalidFormat(
     127                    u"Wrong itens number in breadcrumb %s in %s. \
     128                    You need to send as example (name,url)" % \
     129                    (index,type(obj).__name__)
     130                )
     131        # for objects
     132        elif not hasattr(obj,'name') and not hasattr(obj,'url'):
     133            raise BreadcrumbsInvalidFormat(u"You need to use a tuple like"+ \
     134                " (name,url) or object with name and url attributes for" + \
     135                "breadcrumb.")
     136        return True
     137
     138    def __fill_bds(self,bd):
     139        """
     140        simple interface to add Breadcrumb to bds
     141        """
     142        if hasattr(bd,'name') and hasattr(bd,'url'):
     143            bd = Breadcrumb(bd.name,bd.url)
     144        else:
     145            bd = Breadcrumb(*bd)
     146        if bd.url not in self.__urls:
     147            self.__bds.append(bd)
     148            self.__urls.append(bd.url)
     149
     150    def __iter__(self):
     151        return iter(self.__bds)
     152
     153    def __getitem__(self,key):
     154        return self.__bds[key]
     155
     156    def __repr__(self):
     157        return self.__unicode__()
     158
     159    def __str__(self):
     160        return self.__unicode__()
     161
     162    def __unicode__(self):
     163        return u"Breadcrumbs <%s>" % u", ".join([mark_safe(item.name) for item in \
     164            self[:10]] + [u' ...'])
     165
     166    def all(self):
     167        return self.__bds
  • contrib/breadcrumbs/HowToUse.txt

    diff -urN django-original/contrib/breadcrumbs/HowToUse.txt django/contrib/breadcrumbs/HowToUse.txt
    old new  
     1To use breadcrumbs, after unpack this package you need to follow some steps:
     2
     31 - Set in your settings.py:
     4
     5        #Options to enable Breadcrumbs package:
     6        BREADCRUMBS = False # Enable breadcrumbs
     7        BREADCRUMBS_AUTO_HOME = False # If True, all times first link is (_("Home"),u"/")
     8
     9        # Add BreadcrumbsMiddleware in your MIDDLEWARE_CLASSES, Ex:
     10
     11        MIDDLEWARE_CLASSES = (
     12        ...
     13        'django.contrib.breadcrumbs.middleware.BreadcrumbsMiddleware',
     14        )
     15
     162 - For each view that you want to show on Breadcrumbs, you can use some of
     17examples bellow:
     18
     19        # For two itens (or more) on path
     20        request.breadcrumbs(
     21                (_("Profile"),reverse(UserShowProfile)),
     22                (_("Favorites"),reverse(UserFavs))
     23        )
     24
     25        # For one item on path
     26        request.breadcrumbs( _("Profile"),reverse(UserShowProfile) )
     27
     28        # Without reverse:
     29        request.breadcrumbs( u"Name", "URL" )
     30
     31Breadcrumbs have a path to support flatpages without problems :)
  • contrib/breadcrumbs/__init__.py

    diff -urN django-original/contrib/breadcrumbs/__init__.py django/contrib/breadcrumbs/__init__.py
    old new  
     1from breadcrumbs import Breadcrumb
  • contrib/breadcrumbs/middleware.py

    diff -urN django-original/contrib/breadcrumbs/middleware.py django/contrib/breadcrumbs/middleware.py
    old new  
     1from breadcrumbs import Breadcrumbs
     2
     3class BreadcrumbsMiddleware(object):
     4
     5    def process_request(self,request):
     6        request.breadcrumbs = Breadcrumbs()
     7        request.breadcrumbs._clean()
  • contrib/breadcrumbs/tests.py

    diff -urN django-original/contrib/breadcrumbs/tests.py django/contrib/breadcrumbs/tests.py
    old new  
     1# run this script on your shell
     2from django.contrib.breadcrumbs import Breadcrumbs
     3
     4bds = Breadcrumbs()
     5
     6# fill one per time
     7for i in range(5):
     8    bds( 'name%s' % i,'url%s' % i  )
     9
     10# create a simple class to emulate one object with name and url
     11class emulatedobj(object):
     12    def __init__(self,*args):
     13        self.name = args[0]
     14        self.url = args[1]
     15
     16# add 10 objects
     17bds( [ emulatedobj('name %s' % (i+10), 'url %s' % (i+10)) for i in range(10) ] )
     18
     19# print all
     20for bd in bds:
     21    print bd.name,bd.url
  • contrib/breadcrumbs/utils.py

    diff -urN django-original/contrib/breadcrumbs/utils.py django/contrib/breadcrumbs/utils.py
    old new  
     1from breadcrumbs import Breadcrumbs,BreadcrumbsNotSet
     2from django.contrib.flatpages.models import FlatPage
     3from django.http import Http404
     4
     5def breadcrumbs_for_flatpages(request,flatpage):
     6
     7    if not hasattr(request,'breadcrumbs') or \
     8        not isinstance(request.breadcrumbs,Breadcrumbs):
     9        raise BreadcrumbNotSet(u"You need to setup breadcrumbs to use this " + \
     10                "function.")
     11
     12    if not isinstance(flatpage,FlatPage) or \
     13        not hasattr(flatpage,'id'):
     14        raise TypeError(u"flatpage argument isn't a FlatPage instance or " + \
     15            "not have id.")
     16
     17    paths = []
     18    for part in request.path_info.split(u"/"):
     19        # When split we have u"" for slashes
     20        if len(part) == 0:
     21            continue
     22        # Add slash again
     23        if not part.startswith(u"/"):
     24            part = u"/"+part
     25        if not part.endswith(u"/"):
     26            part = part+u"/"
     27        # If we have something on paths, url for flatpage is composed of what we
     28        # have in path + part. Note that strins in path not have last slash, but
     29        # part have.
     30        if len(paths) > 0:
     31            url = u"".join(paths+[part])
     32        else:
     33            url = part
     34        # if is same url we don't hit database again
     35        # else, get page from FlatPage. If page doesn't exist, we allow raise
     36        # 404 because it is a url design problem, not flatpages or breadcrumbs
     37        # problem.
     38        if url == flatpage.url:
     39            request.breadcrumbs(flatpage.title,flatpage.url)
     40        else:
     41            try:
     42                f = FlatPage.objects.get(url=url)
     43            except FlatPage.DoesNotExist:
     44                raise Http404
     45            else:
     46                request.breadcrumbs(f.title,f.url)
     47        # add last part of path in paths with one slash
     48        paths.append(u"/"+url[1:-1].rpartition(u"/")[-1])
     49
Back to Top