Tagged: python

Django scripting: “AppRegistryNotReady: Apps aren’t loaded yet” solution!

If you want to make a simple script that wants to import your application built on top of the Django framework, you would probably do this code:

import django
from app.models import MyModel

You will probably get this error:

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet

.

Don’t panic!
The solution is to run your application’s setup() before imports, as follows:

import django

if __name__ == '__main__':
    django.setup()
    # import AFTER setup
    from app.models import MyModel
    # from now I can access MyModel!!

Python: compile and run multiple versions without collisions

You have to go find the source code for the Python version that you want.

Example, run an “old” Python 3.6, go here and take the one that we want.

Then get the source code and compile it:

mkdir ~/source ; cd ~/source
wget https://www.python.org/ftp/python/3.6.13/Python-3.6.13.tar.xz
tar xvf Python-3.6.13.tar.xz
cd ~/source/Python-3.6.13
./configure && make
sudo make altinstall

“Et voilà”!

~/source/Python-3.6.13$ python3.6
Python 3.6.13 (default, May 21 2021, 17:12:12) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Django: how to check if we are in debug mode in the template

You will find the information easily, and it seems very simple: in your template, just do:

{% if not debug%}I'm in debug mode!{% endif%}

This won’t work, this is not enough!

In your settings.py file, you must configure the IP’s correctly, which specify that you are / or not / in “development” mode:

INTERNAL_IPS = ['127.0.0.1',]

(Note that this code can be optimized in a way that depends on the environment, for example I made a settings.py which takes this into account).

Django: how to make customized error pages (404, 500, etc.)

When you want to make custom error pages, it’s very simple … once you know how to do it!
The documentation is not very clear on this point…

Here is a summary of my experience, to make custom error pages (404, 500, etc.).
You should first know that errors are called functions (= you cannot do this via generic views).
Then the documentation gives an example, but it’s not enough.
Thanks to Django code shortcuts, you have the function render() to which you can pass a template and a context (= therefore variables).
I used this to create a dictionary that contains the errors, and pass them in a context (= dictionary) with the title and content keys.


Here is the view code that displays “cleanly” the error:

from django.shortcuts import render
from django.utils.translation import gettext_lazy as _
VIEW_ERRORS = {
    404: {'title': _("404 - Page not found"),
          'content': _("A 404 Not found error indicates..."), },
    500: {'title': _("Internal error"),
          'content': _("A 500 Internal error means..."), },
    403: {'title': _("Permission denied"),
          'content': _("A 403 Forbidden error means ..."), },
    400: {'title': _("Bad request"),
          'content': _("A 400 Bad request error means ..."), }, }
def error_view_handler(request, exception, status):
    return render(request, template_name='errors.html', status=status,
                  context={'error': exception, 'status': status,
                           'title': VIEW_ERRORS[status]['title'],
                           'content': VIEW_ERRORS[status]['content']})
def error_404_view_handler(request, exception=None):
    return error_view_handler(request, exception, 404)
def error_500_view_handler(request, exception=None):
    return error_view_handler(request, exception, 500)
def error_403_view_handler(request, exception=None):
    return error_view_handler(request, exception, 403)
def error_400_view_handler(request, exception=None):
    return error_view_handler(request, exception, 400)


Once the views are done, you have to go to the main declaration of your views. This is the urls.py file at the root of your project. If you put the code elsewhere, it will be ignored.

In this file, declare your functions that handle the errors:

handler404 = 'app.views.errors.error_404_view_handler'
handler500 = 'app.views.errors.error_500_view_handler'
handler403 = 'app.views.errors.error_403_view_handler'
handler400 = 'app.views.errors.error_400_view_handler'

And finally, in your templates, create a file errors.html in which you will code your HTML page which shows the error in a clean way.
Note that you have in the context the variables {{ title }} and {{ content }} which are respectively the title and the detail of the error.

Now, how, in “development” mode, test these pages? In practice you cannot, because in development mode, an error displays debugging information, and not your pages!

The solution: make a URL that “simulates” the error. Example with 404: add in your main url’s file: path('404/', error_404_view_handler), and then display the appropriate URL in your browser, ie http://localhost:8000/404/ and you will see the error!

I’m sorry my english is always perfectible, if I’ve made some mistakes, please let a comment and I’ll correct this post. Thanks a lot!

Django >= 2.1: how to make a customized administration, the “clean” way

How to make easily an administration interface for the whole project

On versions of Django < 2.1, it was impossible to overload the administration “properly”.

  • Create a file admin.py at the root of your project (“at the root”, because it is “global” for the whole project)
  • Put that code:
    from django.contrib import admin
    class MyProjectAdminSite(admin.AdminSite):
        title_header = 'My project Admin'
        site_header = 'My project administration'

    Of course, change “MyProject” to the name of your project…
  • In settings.py, replace 'django.contrib.admin' by 'my_app.apps.MyAppAdminConfig',
  • In the file apps.py of your project, hence my_project/my_app/apps.py, declare the administration like this:
    from django.apps import AppConfig
    from django.contrib.admin.apps import AdminConfig
    class MyAppConfig(AppConfig):
        name = 'my_app'
    class MyAppAdminConfig(AdminConfig):
        default_site = 'admin.MyProjectAdminSite'

And… that’s it!