Giter Site home page Giter Site logo

flask-nav's Introduction

Flask-Nav

Flask-Nav is a Flask-Extension to ease the creation of navigational Elements in Applications. It provides means to Express the Navigational structure and different ways to render these, making it easy to custom tailor it for your application.

A motivating example:

from flask import Flask
from flask_nav import Nav
from flask_nav.elements import *

nav = Nav()

# registers the "top" menubar
nav.register_element('top', Navbar(
    View('Widgits, Inc.', 'index'),
    View('Our Mission', 'about'),
    Subgroup(
        'Products',
        View('Wg240-Series', 'products', product='wg240'),
        View('Wg250-Series', 'products', product='wg250'),
        Separator(),
        Label('Discontinued Products'),
        View('Wg10X', 'products', product='wg10x'),
    ),
    Link('Tech Support', href='http://techsupport.invalid/widgits_inc'),
))


app = Flask(__name__)
# [...] (view definitions)

nav.init_app(app)

You can find a small, runnable example application inside the example folder. To run it, install Flask-Appconfig and execute:

$ flask --app=example dev

The full documentation can be found on PyPI.

flask-nav's People

Contributors

mbr avatar qumeric avatar tennyzhuang 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

Watchers

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

flask-nav's Issues

navbar not fully rendered in the example

Dear @mbr,

I like flask-nav, thanks for sharing this code with your insights.
I have run into a minor issue.
The example does not work completely; you don't get to see Widgets Inc. It seems like the first object of Navbar has no effect.
I use flask 0.12.1. This is a navbar which does show Widgets inc and shows the problem.

nav.register_element(
    'top',
    Navbar(
        None, #  NOTE: here is the problem, what ever you put first has no effect
                  #              if you put an object first it is not rendered
        View('Widgits, Inc.', 'index'),
        View('Our Mission', 'about'),
        Subgroup('Products',
                 View('Wg240-Series',
                      'products',
                      product='wg240'),
                 View('Wg250-Series',
                      'products',
                      product='wg250'),
                 Separator(),
                 Text('Discontinued Products'),
                 View('Wg10X',
                      'products',
                      product='wg10x'), ),
        Link('Tech Support', 'http://techsupport.invalid/widgits_inc'), ))

Problem with endpoints which have multiple routes

My packages' version:

Flask (0.12)
Flask-Bootstrap (3.3.7.1)
flask-nav (0.6)

I have a function with multiple routes as below:

from flask_nav.elements import Navbar, View
from flask import Flask
from flask_nav import Nav

nav = Nav()
app = Flask(__name__)
nav.init_app(app)


@app.route('/<profile>/trang-<int:page>/order-<order>-<order_dir>/', )
@app.route('/<profile>/', defaults={'page': 1, 'order': 'sequence', 'order_dir': 'asc'}, )
def index(profile, page, order, order_dir):
    ...


@nav.navigation()
def mk_navbar():
    ...

    return Navbar(
        ...
        View(u'Home', 'index', profile=pf),
        ...
    )

When I tried to access http://localhost:5000/kkm/trang-1/order-list_price-asc/, I got the exception as below:

Traceback (most recent call last):
...
  File "/miniconda2/envs/flecom/lib/python2.7/site-packages/flask_nav/elements.py", line 24, in render
    self))
  File "/miniconda2/envs/flecom/lib/python2.7/site-packages/visitor/__init__.py", line 48, in visit
    return meth(node)
  File "/miniconda2/envs/flecom/lib/python2.7/site-packages/flask_bootstrap/nav.py", line 53, in visit_Navbar
    bar_list.add(self.visit(item))
  File "/miniconda2/envs/flecom/lib/python2.7/site-packages/visitor/__init__.py", line 48, in visit
    return meth(node)
  File "/miniconda2/envs/flecom/lib/python2.7/site-packages/flask_bootstrap/nav.py", line 99, in visit_View
    if node.active:
  File "/miniconda2/envs/flecom/lib/python2.7/site-packages/flask_nav/elements.py", line 89, in active
    append_unknown=not self.ignore_query)
  File "/miniconda2/envs/flecom/lib/python2.7/site-packages/werkzeug/routing.py", line 806, in build
    add(self._converters[data].to_url(values[data]))
KeyError: 'page'

As I tried to debug, I find the problem may lie in active method in flask_nav/elements.py (line 89):

    @property
    def active(self):
        if not request.endpoint == self.endpoint:
            return False

        # rebuild the url and compare results. we can't rely on using get_url()
        # because whether or not an external url is created depends on factors
        # outside our control

        _, url = request.url_rule.build(self.url_for_kwargs,
                                        append_unknown=not self.ignore_query)

        if self.ignore_query:
            return url == request.path

        # take query string into account.
        # FIXME: ensure that the order of query parameters is consistent
        return url == request.full_path

I set a breakpoint at _, url = request.url_rule.build(self.url_for_kwargs, and inspected some variables:

>>>  request.endpoint
'index'
>>> self.endpoint
'index'
>>> request.url_rule
'<Rule \\'/<profile>/trang-<page>/order-<order>-<order_dir>/\\' (HEAD, OPTIONS, GET) -> index>'       
>>> self.url_for_kwargs
{'profile': u'kkm'}

So the rule requires profile, page, order and order_dir. But url_for_kwargs only has profile.
If I change:

        _, url = request.url_rule.build(self.url_for_kwargs,
                                        append_unknown=not self.ignore_query)

to:

       url = url_for(request.endpoint, **self.url_for_kwargs, )

It would work:

>>> url = url_for(request.endpoint, **self.url_for_kwargs)
>>> url
'/kkm/'

That resolved the issue for me. However, I do not know if that would break something else.

Regards,
Hieu

Hide 'Login' button when user authorized

Hello.

Is there a possibility of interaction with current_user.is_authenticated function when building a navigation menu? I want to hide menu item Login when user is authorized and to show when not.

Thanks.

Blueprints + flask-nav (documentation issue)

I like your work here, but I have an issue with Blueprints-style implementations using flask-nav that may just be me not understanding the mechanism (I looked at the source,.. just...)

Ok, so Assuming a have a base navigation navbar (like topnav in the example) and I want to work with it I can't seem to find a way to avoid circular imports with flask-nav. The callback Navbar constructor can place relative imports into quotes (ex: '.root') but unless every single blueprint module implements this function I'll get a render() error since the module currently importing base doesn't have have a .root method.

werkzeug.routing.BuildError: ('blueprintmodule.root', {}, None)

Attempting to use paths to avoid this also doesn't seem to work:

werkzeug.routing.BuildError: ('/', {}, None)

Is there something I'm missing or am I going to have to implement flask route deconstruction in the callback?

Append items to navbar

As "Getting Started" page says:

Items are added by simply passing them to the Navbar-constructor. This is purely convenience, instead it is possible to append to the items attribute of topbar as well.

I have tried to append to the items attribute and failed. Eventually I figured out that this attribute is a tuple so it's impossible to append.
I have found a simple workaround

navbar = Navbar('', ...)
navbar.items = list(navbar.items)

but it doesn't seem like a proper way to do things. Shouldn't Navbar.items be a list instance by default?

Insert form in navbar

Tried googling, but could not find anything about it. Is there a easy way for me to insert a dynamic form into the navbar?

Inheriting `Renderer` breaks all named renderer calls

In my template I have :

{% block navbar %}
{{nav.top.render(renderer='simple')}}
{% endblock %}

And a very basic navbar:

def create_navbar():
    return Navbar(View('Index', 'index.index'))

I inherit and register a renderer:

class FormRenderer(Renderer):
    pass

register_renderer(app, 'form', FormRenderer)

Then, the call to the render(renderer='simple') does not create the navbar, whereas the call to render() will create it.

View.active is incorrect when extra arguments are passed to __init__

I have a Flask Blueprint that looks like this:

@blueprint.route("/rooms/<code>")
def detail(code):
    name = request.args.get('name')
    ...

which responds to /rooms/foo?name=bar with:

  • code = foo
  • name = bar

When I create a View using the same arguments:

view = View(code, 'rooms.detail', code=code, name=name)

It doesn't "activate" when expected:

>>> view.active
False
>>> view.get_url()
"/rooms/foo?name=bar"
>>> request.path"
"/rooms/test
>>> request.url
"http://localhost:5000/rooms/test?name=asdf"

The logic in

return request.path == self.get_url()
is not prepared to handle this case.

Modifying navbar during routing request

Hi,
navbar definition in the flask-nav example is above any routing element.

Is it possible to add some navigational elements inside for example:

@app.route('/about-us/')
   <here i want to add some navbar elements>

and if yes, how?

AttributeError on Python 3.10

I am using flask-nav==0.6 on Python 3.10.4 and meet this error:

  File "/usr/local/lib/python3.10/site-packages/flask_nav/__init__.py", line 49, in <module>
    class ElementRegistry(collections.MutableMapping):
AttributeError: module 'collections' has no attribute 'MutableMapping'

Custom css

How do I add custom styling to the navbar?
Thanks!

parameters "role", "icon" and "info" for elements

How about adding these parameters to the elements (except "separator"):

role=string | list
= roles to check when navbar is rendered against current_user.has_role() (only in an own renderer "authorized")

icon=string
= definition of an bootstrap glyphicon to be placed in front of the text

info=string
= mouse-overtext for nav item

?

Can you provide example of RawTag?

I've tried implementing a RawTag object, but can't figure it out by looking through the source code.

I've tried

  • RawTag("<img src='http://www.w3schools.com/images/colorpicker.gif'>")
  • RawTag('http://www.w3schools.com/images/colorpicker.gif', type='img')

but they don't work.

Can you provide an example in the README/demo?

thanks!

How do I adjust the navbar height?

Hi,

I'm learning Flask and using flask-bootstrap, and I don't like how much vertical space the default bootstrap navbar takes up, and I'm having trouble figuring out how to change that. The flask bootstrap documentation has a section called "Customizing the navbar" that says that I'd want to adjust something in flask-nav, but I read the flask-nav documentation and couldn't see a way to adjust the navbar height.

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.