diff --git a/README.md b/README.md index e3af1b0..97d9ecc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,181 @@ -# themes +# Themes -Django Library Themes \ No newline at end of file +With the django library themes, you are able to include a theme to your django app. It includes an menu-, navigation-, action- and bottombar. + +## Requirements +### Python +You need to ensure that Pillow is available in your python environment. + +## Integration +Clone the library in your django application. + +### Configurations in your settings.py +Add the following line to the list ```INSTALLED_APPS```: +``` + 'themes.apps.ThemesConfig', +``` + +### Configurations in your urls.py +Add the following imports at the top of urls.py, +``` +from django.conf import settings +from django.conf.urls.static import static +``` +the following line to the list ```urlpatterns```: +``` + path('search/', .views.search, name='search'), +``` +and add this lines at the very end (after the definition of ```urlpatterns```: +``` +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) +``` + +### Create a view for the search +Add a view to your views.py: +``` +def search(request): + logger.arning("Search not yet implemented...") + return HttpResponse("Search not implemented...") +``` + +### Settings +Replace the ```STATIC_URL``` definition in your ```settings.py``` with the following lines: +``` +STATIC_ROOT = os.path.join(BASE_DIR, 'data', 'static') +STATIC_URL = 'static/' + +MEDIA_ROOT = os.path.join(BASE_DIR, 'data', 'media') +MEDIA_URL = '/media/' + +``` +### Collect static +Before the static data is available, you need to execute the command +```$ python manage.py collectstatic``` + +## Usage +### Add a template +Before we can use the theme, we need to create a template. Here we use the file ```/templates/app/page.html``` with the following contenet: +``` +{% extends "themes/"|add:settings.page_theme|add:"/base.html" %} + +{% block content %} +{{ page_content|safe }} +{% endblock content %} +``` +In the block content is your content, which will be passed to the template by the variable ```page_content```. + +### Use the template in your view +Now you need to adapt your view. Here is an example view using the theme. +``` +from django.shortcuts import render +from django.conf import settings + +from themes import Context + + +def example(request, rel_path=''): + context = Context(request) # needs to be executed first because of time mesurement + # + return render(request, 'app/page.html', context=context) + +``` + +### Upload the logo +If you havn't created a user yet, you should do so with ```python manage.py createsuperuser ```. + +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)*. + +Upload a logo with the Upload mechanism of *Page image:* and click *Save*. + +### Create a context adaption +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). + +You need to adapt your view method. Add this between the context definition and the return statement: +``` + context_adaption( + context, + request, + title="Additional title", + rel_path=rel_path, + page_content=f"

Dummy page

The rel_path is {rel_path}", + ) +``` + +Here as an example ```context.py```: +``` +import inspect +import logging + +from django.conf import settings +from django.utils.translation import gettext as _ + +from themes import empty_entry_parameters +from themes import gray_icon_url +from themes import color_icon_url + +logger = logging.getLogger(settings.ROOT_LOGGER_NAME).getChild(__name__) + +BACK_UID = "back" +EDIT_UID = "edit" +LOGIN_UID = "login" + + +def context_adaption(context, request, **kwargs): + caller_name = inspect.currentframe().f_back.f_code.co_name + logger.debug("The caller of context_adaption was %s", caller_name) + try: + context.set_additional_title(kwargs.pop('title')) + except KeyError: + pass # no title in kwargs + menubar(context, request, caller_name, **kwargs) + navigationbar(context, request, caller_name, **kwargs) + actionbar(context, request, caller_name, **kwargs) + for key in kwargs: + context[key] = kwargs[key] + logger.debug("context adapted: %s", repr(context)) + + +def menubar(context, request, caller_name, **kwargs): + bar = context[context.MENUBAR] + bar.append_entry( + LOGIN_UID, # uid + _('Settings'), # name + color_icon_url(request, 'settings.png'), # icon + '/app/dummy/settings/page', # url + False, # left + kwargs.get("rel_path") == "dummy/settings/page" # active + ) + finalise_bar(request, bar) # Show bar, if empty + + +def navigationbar(context, request, caller_name, **kwargs): + bar = context[context.NAVIGATIONBAR] + bar.append_entry( + BACK_UID, # uid + _('Back'), # name + gray_icon_url(request, 'back.png'), # icon + 'javascript:history.back()', # url + True, # left + False # active + ) + finalise_bar(request, bar) # Show bar, if empty + + +def actionbar(context, request, caller_name, **kwargs): + bar = context[context.ACTIONBAR] + bar.append_entry( + EDIT_UID, # uid + _('Edit'), # name + color_icon_url(request, 'edit.png'), # icon + '/app/dummy/edit/page', # url + True, # left + kwargs.get("rel_path") == "dummy/edit/page" # active + ) + finalise_bar(request, bar) # Show bar, if empty + + +def finalise_bar(request, bar): + if len(bar) == 0: + bar.append_entry(*empty_entry_parameters(request)) +``` \ No newline at end of file