Skip to content

Commit 759ed09

Browse files
authored
Update example app (#89)
Closes #51
2 parents dc4d66a + 1036f17 commit 759ed09

38 files changed

+558
-349
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ upcoming: Version 2.0.0
99
inside the "simple_menu" subfolder
1010
- Moved CI to GitHub Actions (#67, #72)
1111
- Project is now a part of Jazzband (#54)
12+
- Updated the example app
1213

1314
Version 1.2.1 - Released May 1st, 2016
1415
- Fixing sdist packaging

example/.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
### Django ###
2+
db.sqlite3
3+
db.sqlite3-journal
4+
5+
# Environments
6+
.env
7+
.venv
8+
env/
9+
venv/
10+
ENV/
11+
env.bak/
12+
venv.bak/
13+
14+
# PyCharm
15+
.idea/
16+
17+
# Visual Studio Code
18+
.vscode/

example/README.rst

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,61 @@
1-
Example Project for django-simple-menu
2-
======================================
1+
==============================
2+
django-simple-menu example app
3+
==============================
34

4-
This is a complete example project for django-simple-menu that can be quickly
5-
used to evaluate if django-simple-menu is right for you.
5+
Set up
6+
------
67

7-
Setting up
8-
----------
8+
1. Create a virtualenv, source it, and install dependencies::
9+
10+
python3 -m venv .venv
11+
source .venv/bin/activate
12+
pip install -r requirements.txt
13+
14+
2. Initialize a database and create test users::
15+
16+
python3 manage.py makemigrations
17+
python3 manage.py migrate
18+
python3 manage.py createsuperuser --username admin
19+
python3 manage.py createsuperuser --username user
20+
21+
3. Run server::
22+
23+
python3 manage.py runserver
24+
25+
4. Go to Django administration (probably under http://127.0.0.1:8000/admin/)
26+
and remove superuser rights from the second user you've created.
27+
28+
5. Look around the website, try logging in, have fun :)
929

10-
To setup the project you need to create a new virtualenv directory and install
11-
the dependencies listed in the requirements file::
30+
Screenshots
31+
-----------
32+
.. figure:: ./screenshots/main_page.png
1233

13-
virtualenv testenv
14-
source testenv/bin/activate
15-
pip install -r requirements.txt
34+
Index page of the example app
1635

17-
Next setup the Django instance::
36+
.. figure:: ./screenshots/subpage.png
37+
38+
Page featuring a submenu
39+
40+
.. figure:: ./screenshots/user_page.png
41+
42+
Page only shown to the authenticated users
43+
44+
.. figure:: ./screenshots/secret_page.png
45+
46+
Page only shown to the superusers
47+
48+
Learn more
49+
----------
1850

19-
./manage.py syncdb
51+
Full documentation, including installation and configuration instructions, is
52+
available at https://django-simple-menu.readthedocs.io/.
2053

21-
And finally run the project::
54+
``django-simple-menu`` is released under the *BSD 2-Clause "Simplified" License*.
55+
If you like it, please consider contributing!
2256

23-
./manage.py runserver
57+
``django-simple-menu`` was originally created by
58+
Evan Borgstom <[email protected]> and was further developed by many
59+
contributors_.
2460

25-
Once you access the project at http://127.0.0.1:8000 you will see a menu that
26-
will change depending on if you're logged in, logged in as a staff member or
27-
logged in as a superuser. To fully see the menu system in action you will need
28-
to login to the Django admin and create two new users (one just a staff member
29-
and the other a regular user, you already have a superuser from the syncdb
30-
call) and then login with all three of them to compare the resulting menus.
61+
.. _contributors: https://github.com/jazzband/django-simple-menu/graphs/contributors

example/accounts/apps.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class AccountsConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
6+
name = 'accounts'

example/accounts/menus.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,49 @@
1-
from django.core.urlresolvers import reverse
1+
from django.urls import reverse
2+
3+
from simple_menu import Menu, MenuItem
24

3-
from menu import Menu, MenuItem
45

56
def profile_title(request):
6-
"""
7-
Return a personalized title for our profile menu item
7+
"""Return a personalized title for our profile menu item
88
"""
99
# we don't need to check if the user is authenticated because our menu
1010
# item will have a check that does that for us
1111
name = request.user.get_full_name() or request.user
1212

13-
return "%s's Profile" % name
13+
return f"{name}'s Profile"
1414

15-
Menu.add_item("main", MenuItem("Accounts Index",
16-
reverse("accounts.views.index")))
15+
16+
submenu_items = [
17+
MenuItem(f"Page {i}",
18+
reverse('accounts:subpage', kwargs={'i': i}),
19+
icon=f'{i}-circle')
20+
for i in range(1, 4)
21+
]
22+
Menu.add_item("user", MenuItem("Subpages",
23+
reverse('accounts:subpage', kwargs={'i': 1}),
24+
icon="menu-app",
25+
children=submenu_items))
1726

1827
# this item will be shown to users who are not logged in
19-
Menu.add_item("user", MenuItem("Login",
20-
reverse('django.contrib.auth.views.login'),
21-
check=lambda request: not request.user.is_authenticated()))
28+
Menu.add_item("user", MenuItem("Sign in",
29+
reverse('accounts:sign_in'),
30+
icon='box-arrow-in-right',
31+
check=lambda r: not r.user.is_authenticated))
2232

2333
# this will only be shown to logged in users and also demonstrates how to use
2434
# a callable for the title to return a customized title for each request
2535
Menu.add_item("user", MenuItem(profile_title,
26-
reverse('accounts.views.profile'),
27-
check=lambda request: request.user.is_authenticated()))
28-
Menu.add_item("user", MenuItem("Logout",
29-
reverse('django.contrib.auth.views.logout'),
30-
check=lambda request: request.user.is_authenticated()))
36+
reverse('accounts:profile'),
37+
icon='person-circle',
38+
check=lambda r: r.user.is_authenticated))
3139

3240
# this only shows to superusers
33-
Menu.add_item("user", MenuItem("Admin",
34-
reverse("admin:index"),
35-
separator=True,
36-
check=lambda request: request.user.is_superuser))
41+
Menu.add_item("user", MenuItem("Secret superuser page",
42+
reverse("accounts:super_only"),
43+
icon='incognito',
44+
check=lambda r: r.user.is_superuser))
45+
46+
Menu.add_item("user", MenuItem("Sign out",
47+
reverse('accounts:sign_out'),
48+
icon='box-arrow-right',
49+
check=lambda r: r.user.is_authenticated))
File renamed without changes.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{% extends 'base.html' %}
2+
3+
{% block title %}
4+
Accounts | {{ block.super }}
5+
{% endblock %}
6+
7+
{% block body %}
8+
<main class="py-5">
9+
<div class="container content">
10+
<h1>Welcome!</h1>
11+
<p class="lead">
12+
This is an example website for
13+
<a href="https://github.com/jazzband/django-simple-menu">django-simple-menu</a>.
14+
</p>
15+
<section>
16+
<h2>How to use this example</h2>
17+
<ol>
18+
<li>
19+
Create a superuser:
20+
<code class="user-select-all">python3 manage.py
21+
createsuperuser --username "admin"</code>
22+
</li>
23+
<li>
24+
Create another superuser:
25+
<code class="user-select-all">python3 manage.py
26+
createsuperuser --username "guest"</code>
27+
</li>
28+
<li>
29+
Log in as <code>admin</code> into
30+
<a href="/admin">Django administration</a>
31+
and remove admin and staff rights from
32+
<code>guest</code>.
33+
</li>
34+
<li>
35+
Try logging in and out on the website and visit
36+
the pages in the top menu.
37+
</li>
38+
</ol>
39+
</section>
40+
<section>
41+
<h2>More</h2>
42+
<ul>
43+
<li>
44+
<i class="bi bi-journal-code"></i>
45+
<a href="https://django-simple-menu.readthedocs.io/">
46+
Documentation
47+
</a>
48+
</li>
49+
<li>
50+
<i class="bi bi-github"></i>
51+
<a href="https://github.com/jazzband/django-simple-menu">
52+
Source code
53+
</a>
54+
</li>
55+
</ul>
56+
</section>
57+
</div>
58+
</main>
59+
{% endblock %}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{% extends 'base.html' %}
2+
3+
{% block title %}
4+
Your profile | {{ block.super }}
5+
{% endblock %}
6+
7+
{% block body %}
8+
<main class="py-5">
9+
<section class="container">
10+
<h1>{{ request.user.get_full_name|default:"" }}
11+
(@{{ request.user.username }})</h1>
12+
<p>
13+
<strong>E-Mail:</strong> {{ request.user.email }}
14+
</p>
15+
</section>
16+
<section class="container content">
17+
<p>
18+
The menu item for this page is being shown to everyone,
19+
who is authenticated:
20+
</p>
21+
<pre><code>Menu.add_item("user", MenuItem(profile_title,
22+
reverse('accounts:profile'),
23+
icon='person-circle',
24+
<mark>check=lambda r: r.user.is_authenticated</mark>))</code></pre>
25+
<p>
26+
Also take a look at the <code>profile_title</code>. It's not a string,
27+
but a callable, which accepts the request object. In our case,
28+
it renders the user's name on the button:
29+
</p>
30+
<pre><code>def profile_title(request):
31+
name = request.user.get_full_name() or request.user
32+
return f"{name}'s Profile"</code></pre>
33+
</section>
34+
</main>
35+
{% endblock %}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{% extends 'base.html' %}
2+
3+
{% block title %}
4+
Sign in | {{ block.super }}
5+
{% endblock %}
6+
7+
{% block body %}
8+
<main class="p-4">
9+
<section class="container w-25 mx-auto mb-5">
10+
<form action="{% url 'accounts:sign_in' %}" method="post">
11+
{% csrf_token %}
12+
<h1>Sign in</h1>
13+
14+
<div class="mb-3">
15+
<label for="username">Username</label>
16+
<input type="text" class="form-control" id="username"
17+
name="username" autofocus>
18+
</div>
19+
<div class="mb-3">
20+
<label for="password">Password</label>
21+
<input type="password" class="form-control"
22+
id="password" name="password">
23+
</div>
24+
25+
<button class="btn btn-lg btn-primary" type="submit">
26+
Sign in
27+
</button>
28+
</form>
29+
</section>
30+
<section class="container content">
31+
The menu item for this page is being shown to everyone,
32+
who is not authenticated:
33+
<pre><code>Menu.add_item("user", MenuItem("Sign in",
34+
reverse('accounts:sign_in'),
35+
icon='box-arrow-in-right',
36+
<mark>check=lambda r: not r.user.is_authenticated</mark>))</code></pre>
37+
</section>
38+
</main>
39+
{% endblock %}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{% extends 'base.html' %}
2+
3+
{% block title %}
4+
Subpage | {{ block.super }}
5+
{% endblock %}
6+
7+
{% block body %}
8+
<main class="py-5">
9+
<section class="container">
10+
<h1>This is a subpage</h1>
11+
</section>
12+
<section class="container content">
13+
<p>
14+
There are three identical pages that are nested inside their
15+
parent menu item:
16+
</p>
17+
<pre><code>submenu_items = [...]
18+
Menu.add_item("user", MenuItem("Subpages",
19+
reverse('accounts:subpage', kwargs={'i': 1}),
20+
icon="menu-app",
21+
<mark>children=submenu_items</mark>))</code></pre>
22+
<p>
23+
Note that the second navigation bar is only shown for the pages
24+
that have a submenu. You can check it in the template:
25+
</p>
26+
<pre><code>&lbrace;% <mark>if has_submenu</mark>
27+
&lt;!-- display submenu --&gt;
28+
&lbrace;% endif %}</code></pre>
29+
30+
<p>
31+
By default, the parent will not be marked active if their child
32+
active. The example site changes this behavior using a setting:
33+
</p>
34+
<pre><code>MENU_SELECT_PARENTS = True</code></pre>
35+
</section>
36+
</main>
37+
{% endblock %}

0 commit comments

Comments
 (0)