|
@@ -1,3 +1,181 @@
|
1
|
|
-# themes
|
|
1
|
+# Themes
|
2
|
2
|
|
3
|
|
-Django Library Themes
|
|
3
|
+With the django library themes, you are able to include a theme to your django app. It includes an menu-, navigation-, action- and bottombar.
|
|
4
|
+
|
|
5
|
+## Requirements
|
|
6
|
+### Python
|
|
7
|
+You need to ensure that Pillow is available in your python environment.
|
|
8
|
+
|
|
9
|
+## Integration
|
|
10
|
+Clone the library in your django application.
|
|
11
|
+
|
|
12
|
+### Configurations in your settings.py
|
|
13
|
+Add the following line to the list ```INSTALLED_APPS```:
|
|
14
|
+```
|
|
15
|
+ 'themes.apps.ThemesConfig',
|
|
16
|
+```
|
|
17
|
+
|
|
18
|
+### Configurations in your urls.py
|
|
19
|
+Add the following imports at the top of urls.py,
|
|
20
|
+```
|
|
21
|
+from django.conf import settings
|
|
22
|
+from django.conf.urls.static import static
|
|
23
|
+```
|
|
24
|
+the following line to the list ```urlpatterns```:
|
|
25
|
+```
|
|
26
|
+ path('search/', <your-app>.views.search, name='search'),
|
|
27
|
+```
|
|
28
|
+and add this lines at the very end (after the definition of ```urlpatterns```:
|
|
29
|
+```
|
|
30
|
+if settings.DEBUG:
|
|
31
|
+ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
|
32
|
+```
|
|
33
|
+
|
|
34
|
+### Create a view for the search
|
|
35
|
+Add a view to your views.py:
|
|
36
|
+```
|
|
37
|
+def search(request):
|
|
38
|
+ logger.arning("Search not yet implemented...")
|
|
39
|
+ return HttpResponse("Search not implemented...")
|
|
40
|
+```
|
|
41
|
+
|
|
42
|
+### Settings
|
|
43
|
+Replace the ```STATIC_URL``` definition in your ```settings.py``` with the following lines:
|
|
44
|
+```
|
|
45
|
+STATIC_ROOT = os.path.join(BASE_DIR, 'data', 'static')
|
|
46
|
+STATIC_URL = 'static/'
|
|
47
|
+
|
|
48
|
+MEDIA_ROOT = os.path.join(BASE_DIR, 'data', 'media')
|
|
49
|
+MEDIA_URL = '/media/'
|
|
50
|
+
|
|
51
|
+```
|
|
52
|
+### Collect static
|
|
53
|
+Before the static data is available, you need to execute the command
|
|
54
|
+```$ python manage.py collectstatic```
|
|
55
|
+
|
|
56
|
+## Usage
|
|
57
|
+### Add a template
|
|
58
|
+Before we can use the theme, we need to create a template. Here we use the file ```<your-app>/templates/app/page.html``` with the following contenet:
|
|
59
|
+```
|
|
60
|
+{% extends "themes/"|add:settings.page_theme|add:"/base.html" %}
|
|
61
|
+
|
|
62
|
+{% block content %}
|
|
63
|
+{{ page_content|safe }}
|
|
64
|
+{% endblock content %}
|
|
65
|
+```
|
|
66
|
+In the block content is your content, which will be passed to the template by the variable ```page_content```.
|
|
67
|
+
|
|
68
|
+### Use the template in your view
|
|
69
|
+Now you need to adapt your view. Here is an example view using the theme.
|
|
70
|
+```
|
|
71
|
+from django.shortcuts import render
|
|
72
|
+from django.conf import settings
|
|
73
|
+
|
|
74
|
+from themes import Context
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+def example(request, rel_path=''):
|
|
78
|
+ context = Context(request) # needs to be executed first because of time mesurement
|
|
79
|
+ #
|
|
80
|
+ return render(request, 'app/page.html', context=context)
|
|
81
|
+
|
|
82
|
+```
|
|
83
|
+
|
|
84
|
+### Upload the logo
|
|
85
|
+If you havn't created a user yet, you should do so with ```python manage.py createsuperuser ```.
|
|
86
|
+
|
|
87
|
+Visit http://127.0.0.1:8000/admin and login with that user. Klick on *Settings* in the *Themes* section and then on the *Settings object (1)*.
|
|
88
|
+
|
|
89
|
+Upload a logo with the Upload mechanism of *Page image:* and click *Save*.
|
|
90
|
+
|
|
91
|
+### Create a context adaption
|
|
92
|
+From this point on, you can see a blank themed page. With the adaption of the context variable, you are able to define the content of the 3 bars on the top and the page_content itself. The bottom bar will be defined in the django administration page (THEMES->Bottom bars->ADD BOTTOM BAR).
|
|
93
|
+
|
|
94
|
+You need to adapt your view method. Add this between the context definition and the return statement:
|
|
95
|
+```
|
|
96
|
+ context_adaption(
|
|
97
|
+ context,
|
|
98
|
+ request,
|
|
99
|
+ title="Additional title",
|
|
100
|
+ rel_path=rel_path,
|
|
101
|
+ page_content=f"<h1> Dummy page</h1>The rel_path is {rel_path}",
|
|
102
|
+ )
|
|
103
|
+```
|
|
104
|
+
|
|
105
|
+Here as an example ```context.py```:
|
|
106
|
+```
|
|
107
|
+import inspect
|
|
108
|
+import logging
|
|
109
|
+
|
|
110
|
+from django.conf import settings
|
|
111
|
+from django.utils.translation import gettext as _
|
|
112
|
+
|
|
113
|
+from themes import empty_entry_parameters
|
|
114
|
+from themes import gray_icon_url
|
|
115
|
+from themes import color_icon_url
|
|
116
|
+
|
|
117
|
+logger = logging.getLogger(settings.ROOT_LOGGER_NAME).getChild(__name__)
|
|
118
|
+
|
|
119
|
+BACK_UID = "back"
|
|
120
|
+EDIT_UID = "edit"
|
|
121
|
+LOGIN_UID = "login"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+def context_adaption(context, request, **kwargs):
|
|
125
|
+ caller_name = inspect.currentframe().f_back.f_code.co_name
|
|
126
|
+ logger.debug("The caller of context_adaption was %s", caller_name)
|
|
127
|
+ try:
|
|
128
|
+ context.set_additional_title(kwargs.pop('title'))
|
|
129
|
+ except KeyError:
|
|
130
|
+ pass # no title in kwargs
|
|
131
|
+ menubar(context, request, caller_name, **kwargs)
|
|
132
|
+ navigationbar(context, request, caller_name, **kwargs)
|
|
133
|
+ actionbar(context, request, caller_name, **kwargs)
|
|
134
|
+ for key in kwargs:
|
|
135
|
+ context[key] = kwargs[key]
|
|
136
|
+ logger.debug("context adapted: %s", repr(context))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+def menubar(context, request, caller_name, **kwargs):
|
|
140
|
+ bar = context[context.MENUBAR]
|
|
141
|
+ bar.append_entry(
|
|
142
|
+ LOGIN_UID, # uid
|
|
143
|
+ _('Settings'), # name
|
|
144
|
+ color_icon_url(request, 'settings.png'), # icon
|
|
145
|
+ '/app/dummy/settings/page', # url
|
|
146
|
+ False, # left
|
|
147
|
+ kwargs.get("rel_path") == "dummy/settings/page" # active
|
|
148
|
+ )
|
|
149
|
+ finalise_bar(request, bar) # Show bar, if empty
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+def navigationbar(context, request, caller_name, **kwargs):
|
|
153
|
+ bar = context[context.NAVIGATIONBAR]
|
|
154
|
+ bar.append_entry(
|
|
155
|
+ BACK_UID, # uid
|
|
156
|
+ _('Back'), # name
|
|
157
|
+ gray_icon_url(request, 'back.png'), # icon
|
|
158
|
+ 'javascript:history.back()', # url
|
|
159
|
+ True, # left
|
|
160
|
+ False # active
|
|
161
|
+ )
|
|
162
|
+ finalise_bar(request, bar) # Show bar, if empty
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+def actionbar(context, request, caller_name, **kwargs):
|
|
166
|
+ bar = context[context.ACTIONBAR]
|
|
167
|
+ bar.append_entry(
|
|
168
|
+ EDIT_UID, # uid
|
|
169
|
+ _('Edit'), # name
|
|
170
|
+ color_icon_url(request, 'edit.png'), # icon
|
|
171
|
+ '/app/dummy/edit/page', # url
|
|
172
|
+ True, # left
|
|
173
|
+ kwargs.get("rel_path") == "dummy/edit/page" # active
|
|
174
|
+ )
|
|
175
|
+ finalise_bar(request, bar) # Show bar, if empty
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+def finalise_bar(request, bar):
|
|
179
|
+ if len(bar) == 0:
|
|
180
|
+ bar.append_entry(*empty_entry_parameters(request))
|
|
181
|
+```
|