Code Monkey home page Code Monkey logo

django-treenav's Introduction

django-treenav

Build Status

master:Build Status
develop:Build Status

An extensible, hierarchical, and pluggable navigation system for Django sites.

django-treenav was designed from the start to live independent of a CMS implementation. As a separate application, treenav can easily be integrated into existing, custom setups and does not enforce or require users to use a particular content management system.

Sharing the same principles, django-pagelets integrates seamlessly with treenav and can be used together to create a flexible CMS product.

For complete documentation checkout, http://django-treenav.readthedocs.org

Features

  • Generic functionality with multiple URL specifications: get_absolute_url(), reverse(), or raw URLs
  • Packaged with templates to render the tree hierarchy with nested <ul>'s, but can easily be overridden with custom templates
  • Easily customize each item's template or fall back to a default menuitem.html
  • Useful CSS classes for flexible UI customization
  • Automatically sets "active" on item and item's parents if PATH_INFO is equal to item.href
  • Efficient: minimizes database access with django-mptt functionality
  • Caches the tree so that repeated page views do not hit the database.
  • Simple links in the MenuItem list view for refreshing the cache and href from the database.

Requirements

Using the demo

For a quick demo, follow these steps:

  1. Create a virtualenv. (This example uses mkvirtualenv, but there are many other ways to do it):

    $ mkvirtualenv django-treenav
    
  2. Check out the code and install the requirements:

    (django-treenav)$ git clone git://github.com/caktus/django-treenav.git
    (django-treenav)$ cd django-treenav/
    (django-treenav)~/django-treenav/$ pip install -Ur dev-requirements.txt
    
  3. Run migrations and create a superuser so you can login to the Django admin:

    (django-treenav)~/django-treenav$ python manage.py migrate
    (django-treenav)~/django-treenav$ python manage.py createsuperuser
    
  4. Run the server:

    (django-treenav)~/django-treenav$ python manage.py runserver
    
  5. Visit http://localhost:8000/ in your browser and follow the instructions.

Installation

  1. Install the app with pip:

    pip install django-treenav
    
  2. Add to your INSTALLED_APPS and run migrate:

    INSTALLED_APPS = (
        ...,
        'mptt',
        'treenav',
    )
    
  3. Include these context processors:

    TEMPLATES = [
      {
        'OPTIONS': {
          'context_processors': [
            "django.template.context_processors.request",
            "treenav.context_processors.treenav_active",
          ],
        },
      },
    ]
    
  4. Add these urls:

    urlpatterns = [
        url(r'^treenav/', include('treenav.urls')),
    ]
    

Maintainer Information

We use Github Actions to lint (using pre-commit, black, isort, and flake8), test (using tox and tox-gh-actions), calculate coverage (using coverage), and build documentation (using sphinx).

We have a local script to do these actions locally, named maintain.sh:

$ ./maintain.sh

A Github Action workflow also builds and pushes a new package to PyPI whenever a new Release is created in Github. This uses a project-specific PyPI token, as described in the PyPI documentation here. That token has been saved in the PYPI_PASSWORD settings for this repo, but has not been saved anywhere else so if it is needed for any reason, the current one should be deleted and a new one generated.

As always, be sure to bump the version in treenav/__init__.py before creating a Release, so that the proper version gets pushed to PyPI.

Development sponsored by Caktus Consulting Group, LLC.

django-treenav's People

Contributors

benred42 avatar caladd avatar copelco avatar dpoirier avatar itsdkey avatar jmyles avatar kgodey avatar kmtracey avatar mlavin avatar ringemup avatar tobiasmcnulty avatar vkurup avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-treenav's Issues

full_tree isn't working as expected on a third-tier list item

Hi guys – if this isn't a bug and I've missed something, I apologize. I can't figure out what I might be doing wrong though. I'm running Django 1.4.12

I have the following menu defined in django-treenav:

treenav

I'm trying to display the primary navigation and secondary navigation full tree, drop-down style. (Primary navigation will only be one-level in practice, but for robustness, I'm trying to build it out for flexibility.) Here are the template tags I'm using:

{% show_treenav 'primary-navigation' full_tree='True' %}
{% show_treenav 'secondary-navigation' full_tree='True' %}

The problem I'm having is that in the secondary navigation, the third tier (what I've highlighted in yellow in the screenshot) isn't displaying in the menu unless I'm on its parent page, "glossary-terms." I took a guess, and putting an integer before or after full_tree='True' throws an error.

Delete from Admin changelist fails

Attempting to delete an item from the admin's changelist fails because it uses treenav's MenuItemManager instead of MPTT's TreeManager. Deleting from the admin's change form, however, does work.

AttributeError on save any model without get_absolute_url method

If any model in one's site has no get_absolute_url() method, then when you save it, treenav raises an attribute error on line 218 of models.py. A try/except clause there would solve the problem:

    if sender in menu_models:
        ct = ContentType.objects.get_for_model(sender)
        items = MenuItem.objects.filter(content_type=ct, object_id=instance.pk)
        for item in items:
-            if item.href != instance.get_absolute_url():
-                item.href = instance.get_absolute_url()
+            try:
+                item_url = instance.get_absolute_url()
+            except AttributeError:
+                pass
+            else:
+                item.href = item_url
                 item.save()

1.0 tag is broken for django 1.9.X

Hi! I was trying to figure out what's happening but couldn't. the traceback is:

web_1 | Traceback (most recent call last):
web_1 | File "manage.py", line 10, in
web_1 | execute_from_command_line(sys.argv)
web_1 | File "/usr/local/lib/python2.7/dist-packages/django/core/management/init.py", line 350, in execute_from_command_line
web_1 | utility.execute()
web_1 | File "/usr/local/lib/python2.7/dist-packages/django/core/management/init.py", line 342, in execute
web_1 | self.fetch_command(subcommand).run_from_argv(self.argv)
web_1 | File "/usr/local/lib/python2.7/dist-packages/django/core/management/init.py", line 176, in fetch_command
web_1 | commands = get_commands()
web_1 | File "/usr/local/lib/python2.7/dist-packages/django/utils/lru_cache.py", line 100, in wrapper
web_1 | result = user_function(_args, *_kwds)
web_1 | File "/usr/local/lib/python2.7/dist-packages/django/core/management/init.py", line 71, in get_commands
web_1 | for app_config in reversed(list(apps.get_app_configs())):
web_1 | File "/usr/local/lib/python2.7/dist-packages/django/apps/registry.py", line 137, in get_app_configs
web_1 | self.check_apps_ready()
web_1 | File "/usr/local/lib/python2.7/dist-packages/django/apps/registry.py", line 124, in check_apps_ready
web_1 | raise AppRegistryNotReady("Apps aren't loaded yet.")
web_1 | django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

I was able to reproduce the same error on the example project, just by upgrading the django version to 1.9.1

Thanks!

pass template to templatetags

I have a suggestion:
Could tags: render_menu_children, show_treenav, single_level_menu
take an optional argument that would be an template_name.html? If the template_name isn't passed it should take the default templates offered by the app (treenav/menuitem.html or 'treenav/menucrumbs.html')

OR!
Could there be an get_template method that would get the template based on the slug of the menuitem from the templates?
Example
root - slug: root - parent: ---
a - slug: a - parent: root
b - slug: b - parent: root
aa - slug: aa - parent: a

  1. For "aa" in templates/treenav find: root/a/aa.html
  2. If root/a/aa.html isn't there, get root/a/menuitem.html (get default template for "a" children)
  3. If root/a/menuitem.html isn't there, get root/a.html (get template for parent "aa" parent)
  4. If root/a.html isn't there, get root/menuitem.html (get default template for "root" children)
  5. If root/a.html isn't there, get menuitem.html (get default template)

This could help in:

  1. Building an top menu and a footer menu using the same tag and just changing the template so the can be different, or building the top menu with show_treenav (full_tree = True) and render_menu_children with a different template -> basically two different templates = more flexability
  2. Building a main menu and using a different template for the children

Menu items are still not ordered correctly.

If menu is printed in template items are in different order than it should be by 'Order' field.

I tried to use both latest version from github of django-treenav and django-mptt, but issue is still same.

There were two issues in past which are closed, but I don't have permission to reopen either of them.

Django 2.1.1 error

Hi, i have this Error
TypeError: init() missing 1 required positional argument: 'on_delete'

Sample project does not work with Django 2.0.9

Django==2.0.9
django-js-asset==1.1.0
django-mptt==0.9.1
-e git://github.com/caktus/django-treenav.git@8f81619a8598790d1c2dc7bf77ba9d8e9e9564e6#egg=django_treenav
pytz==2018.7
!   ³ django-treenav  /d/w/g/django-treenav   develop  sample_project  ./manage.py  migrate                                                         
Traceback (most recent call last):
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/urls/conf.py", line 17, in include
    urlconf_module, app_name = arg
ValueError: too many values to unpack (expected 2)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
    utility.execute()
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/management/__init__.py", line 365, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/management/base.py", line 332, in execute
    self.check()
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/management/base.py", line 364, in check
    include_deployment_checks=include_deployment_checks,
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/management/commands/migrate.py", line 58, in _run_checks
    issues.extend(super()._run_checks(**kwargs))
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/management/base.py", line 351, in _run_checks
    return checks.run_checks(**kwargs)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/checks/registry.py", line 73, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/checks/urls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/core/checks/urls.py", line 23, in check_resolver
    return check_method()
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/urls/resolvers.py", line 399, in check
    for pattern in self.url_patterns:
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/utils/functional.py", line 36, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/urls/resolvers.py", line 540, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/utils/functional.py", line 36, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/urls/resolvers.py", line 533, in urlconf_module
    return import_module(self.urlconf_name)
  File "/data/venvs/django-treenav/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/data/work/github/django-treenav/sample_project/urls.py", line 8, in <module>
    url(r'^admin/', include(admin.site.urls)),
  File "/data/venvs/django-treenav/lib/python3.5/site-packages/django/urls/conf.py", line 27, in include
    'provide the namespace argument to include() instead.' % len(arg)
django.core.exceptions.ImproperlyConfigured: Passing a 3-tuple to include() is not supported. Pass a 2-tuple containing the list of patterns and app_name, and provide the namespace argument to include() instead.

coveralls fails locally

With the change that we had to make for coveralls/tox2.0, we now run coveralls locally since it's in tox.ini. (Before it was only in .travis.yml).

This fails for me locally because I don't have the tokens that Travis has:

You have to provide either repo_token in .coveralls.yml, or launch via Travis
ERROR: InvocationError: '/home/vkurup/dev/django-treenav/.tox/coverage/bin/coveralls'

I haven't figured out what the proper solution is yet... It would be nice to have coveralls run only on Travis, if that's possible.

MenuItem object_id is not of the most flexible type.

Consider an object whose pk is a UUID stored in a CharField. The generic foreign key on menuitem cannot support this currently because it is limited to a PositiveIntegerField.

A migration to a CharField with db_index=True would allow for more flexibility, whilst maintain backwards compatibility with existing data.

Items appear in wrong order in admin?

Child items of top-level menu items are appearing in the treenav changelist as if they were actually children of a different menu item, and all the trees are sort of mingled together. I assume this has something to do with the Django admin sorting by only one field at a time? Is there any way to fix it? If I can figure out how I'll try to attach a screenshot of the issue.

To reproduce:

  • Create multiple independent menu trees (e.g. main menu, footer menu, etc), each with at least 2 levels, and with orders assigned to each item
  • View changelist
  • To see what's wrong, look at the apparent tree based on the indent levels, and then at the contents of the Parent field for each item.

Allow order beyond 0-9

0-9 are insufficient for ordering long menus. Free entry for the order field would be ideal, but if there's some big reason why that won't work, how about at least expanding the limit to 0-50 or something?

reordering models has caused major problems in the database

Hello,
I have a strange problem. I was reordering the navigation on a client's site and the main list suddenly completely rearranged itself. Clearing the cache and refreshing hrefs isn't helping, and I tried to do a cache.clear from the shell, and nothing seems to be working. You can see the problem here:

screen shot 2015-03-12 at 4 29 11 pm

When you click on "skin type", you can see that the parent is actually "tan safely", not "main-nav"

screen shot 2015-03-12 at 4 38 54 pm

This is the correct ordering, but that's not what is showing up in the Menu Items list or the navigation of the site. This is the second time this has happened to me on different sites in the past two weeks, and it seems like a pretty major issue, so I'm wondering if I'm doing something wrong in my site configuration. Any ideas?

Thanks,

Kasey

Active node only?

Hi,

More of a question than a bug, but I couldn't find a way of identifying the current node in the template?

item.active identifies the path down to the current node, which is good for many use-cases.

However, I'd like to use an if statement in the template to identify the current node only, is that possible?

Django 1.10 Compatibility

There are a number of places in the test_views.py file that reverse urls with a dotted Python path, which will be removed in Django 1.10 in favor of named urls. I believe the use of django.contrib.contenttypes.generic will be deprecated as well, with its functions spread out between the fields, forms, and admin submodules of django.contrib.contenttypes.

Document Future Updates

I don't see a lot of feature development in the future of this project meaning that we should cut a v1.0 and establish a policy of updates related to Django/Django-MPTT updates going forward.

Major update for Dj Treenav

I'm creating this issue so we can work on the major update of this package.

What is the problem?
DjTreenav does not support the newest Django and python versions (does not support officially) and it supports deprecated versions like python2.7-3.4, and Django 1.8.

To make this package up-to-date we should check and make adjustments so this package can be used with python3.6+ and Dj 2.2+

Based on that I want to suggest dropping support for deprecated versions so we can make the right and up-to-date changes that are followed in Django and Python.

To do that I think this should be done:

  1. Based on the PR I've made and @Audiosutras suggestions (link) we should offer a small database sample in our sample project so a User considering using DjTreenav can fully check it's potential without installing it in his project.
  2. Restructure the project (link) so we can run tests "the Django way" instead of creating mini hacks like run_tests.py
  3. Update travis.yml and tox.ini to support the newest versions of Python and Django.
  4. Updating the documentation if necessary.

To do that I suggest doing things in the following order: 3-2-1-4.

The only problem is that each point will depend on a different one, for example, to check if the code is okay we need to support python3.8 in tox and travis. So I think that theses points should be done on a single branch.

Any suggestions?

Translations

Many strings are marked for translation but there are some which are not. We should mark all strings for translation and generated the .po files.

Is this project still alive?

Hi there,
Is this project still alive? I see that it has some issues with newer Django versions. Maybe it's possible to reactivate this app?

Any suggestions?

Make a menu item active when page doesn't directly belong to navtree

Let's say I have nav tree which looks like this:

Books:
--Science fiction
--Fantasy

I have a model Book which represents a book. Since there are lots books, they aren't inserted into treenav (treenav show categories only), but it is assumed, that a book is under, for example, Fantasy category, so when opening Book detail view page, I'd like to make Books and Fantasy menu items active. Is there any possibility to do this via some template tag or something?

MenuItemForm should call super in clean

Currently MenuItemForm does not call the parent clean method. This means that the uniqueness validation is not run. From the Django docs http://docs.djangoproject.com/en/1.2/topics/forms/modelforms/#overriding-the-clean-method

By default the clean() method validates the uniqueness of fields that are marked as unique, unique_together or unique_for_date|month|year on the model. Therefore, if you would like to override the clean() method and maintain the default validation, you must call the parent class's clean() method.

Update the Sample Project

The sample project could use a little more attention and updates to continue to work with the latest versions of Django.

MPTT Updates

Using django-mptt==0.5.2 we currently get the warning

Implicit manager MenuItem.tree will be removed in django-mptt 0.6.  Explicitly define a TreeManager() on your model to remove this warning.

Also we are using mptt.register which is no longer recommend if you have control over the model definition which we do. We should update the usage of django-mptt and test vs django-mptt master. The current setup.py requirement is very strict and we should see if it can be changed to django-mptt>=0.5.2.

full_tree not observed - overwritten with None; use int instead of bool?

I can't get my menu to render consistently in full_tree mode. Trying to track this down, here's the only explanation I've come up with:

Because the full_tree argument is in the tag itself rather than the template context, and because Django's template variable resolver doesn't seem to process Python booleans, the CaktNode's render() method always overwrites full_tree with None when evaluating kwargs in treenav/templatetags/init.py, line 42-46 (unless one adds a full_tree variable to the global context, which would then force all menus on the page to operate in full_tree mode).

The only solution I can come up with at the moment is to use an integer instead of a string representation of a boolean for the full_tree variable. This would mean two changes: updating the documentation, and changing line 94 of treenav/templatetags/treenav.py to simply assign full_tree instead of checking it against the string 'True'.

Does that make any sense?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.