mirror of
https://expo.survex.com/repositories/expoweb/.git/
synced 2024-11-30 22:01:58 +00:00
100 lines
9.3 KiB
HTML
100 lines
9.3 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
<title>Handbook Troggle and Django</title>
|
||
<link rel="stylesheet" type="text/css" href="/css/main2.css" />
|
||
</head>
|
||
<body><style>body { background: #fff url(/images/style/bg-system.png) repeat-x 0 0 }</style>
|
||
<h2 id="tophead">CUCC Expedition Handbook</h2>
|
||
<h1>Django and Troggle</h1>
|
||
|
||
<h3>Django Versions and troggle</h3>
|
||
<p>Troggle is built on top of the django framework. In 2019 we had let ourselves get rather behind in keeping up to date with the current django version and this held us back from upgrading the operating system - which we needed to do. Troggle uses several community-contributed django plugins and each of these had their own version dependencies. We also got caught up with out of date and deprecated python language features.
|
||
<p>A ridiculous amount of work was required to get to a situation where troggle was running on relatively recent and nearly security-in-date versions of python, django, plugins and linux by Summer 2020. We don't want that to happen again.
|
||
|
||
<h3 id="3sent">Three sentence intro to Django for python programmers</h3>
|
||
<ul>
|
||
<li>There are many 'magic' function calls autogenerated. So when we create an object of <var>'Cave'</var> class (subclass of Django <var>Model</var>), with a property (foreign key) which is an instance of the CaveAndEntrance class, we automagically define functions such as:
|
||
<ul>
|
||
<li><var>Cave.objects.filter()</var>
|
||
<li><var>Cave.objects.all()</var>
|
||
<li><var>Cave.caveandentrance_set.all</var>
|
||
</ul>
|
||
note that the suffix on a name '<a href="https://docs.djangoproject.com/en/dev/topics/db/queries/#backwards-related-objects"><var>_set</var></a>' actually denotes a function call to the database to find all objects of class "CaveAndEntrance" which are foreign-keyed on that object "Cave". Don't let this upset you. Yes, at a deeper level there is SQL happening. (The underline character and lower-casing usually denotes a dereferencing operation in Django queries, but in this case it is a
|
||
<a href="https://docs.djangoproject.com/en/dev/topics/db/queries/#backwards-related-objects">backwards relation</a>, but we don't do anything that devious in troggle.)
|
||
|
||
<li>You will get very familiar with the <a href="https://docs.djangoproject.com/en/3.2/">online documentation</a>. be sure to be looking that the flavour for the right release of Django (indicated on the bottom-right of the screen: the link here goes to v3.2). You can read it in Polish, Indonesian, Brazilian-Portuguese or whatever if you prefer.
|
||
|
||
<li>Django has a good process for migrating both the python code and the SQL database to later versions of Django via <a href="https://docs.djangoproject.com/en/dev/topics/migrations/">'migrations'</a>. Note that even though Expo imports all the data from files and its database is ephemeral (but it is intensely used for cross-referencing), the database schema still needs to be migrated.
|
||
</ul>
|
||
|
||
<h4>Django versions and deprecation</h4>
|
||
|
||
<a href="https://www.djangoproject.com/download#supported-versions">
|
||
<img border="1" class="onright" width="250px" src='django-v3.2-6.0-schedule.jpg'/></a>
|
||
|
||
<ul>
|
||
<li>Django has a mature and reliable release programme: <a href="https://docs.djangoproject.com/en/dev/releases/">docs.djangoproject.com<wbr>/en/<wbr>dev/<wbr>releases/</a>
|
||
<li>Django pre-announces which features will be deprecated: <a href="https://docs.djangoproject.com/en/dev/internals/deprecation/">docs.djangoproject.com<wbr>/en/<wbr>dev/<wbr>internals/<wbr>deprecation/</a>
|
||
<li>Django release schedule: <a href="https://www.djangoproject.com/download/">supported versions timetable</a>
|
||
<li>Significant new Django versions are released every 8 months. Deprecated features after removed after the two subsequent versions.
|
||
</ul>
|
||
<p>This may seem overly pedantic and heavyweight, but this is exactly what we need when we are supporting software over decades. When we use software in troggle which is not so well organised, we really feel the pain.
|
||
|
||
<h4>Django plugins</h4>
|
||
<p>We do not just use our own code and django. We also use django plugins (known as "apps") too. These can do such things as image re-sizing, user authentication with captchas, PayPal processing or mailing list integration. Unfortunately django plugins are volunteer efforts and do not have the same defined update management process as django itself, so release schedules are rather random. They cause merry hell when upgrading troggle to use a new version of django.
|
||
|
||
<p>Every extra plugin increases the "vulnerability surface" of troggle with respect to django upgrade problems so we now only install a new
|
||
plugin if it is really, really necessary and we have removed as many as we could. For example, when django-staticfiles broke during one upgrade
|
||
we discovered that we weren't really using it and could work around it, so we are not planning on reinstalling staticfiles.
|
||
|
||
<h4 id="4layer">Why we still use django</h4>
|
||
<p>Well we <a href="trog2030.html">might not use django indefinitely</a>, but unlike many frameworks the necessary functions are separately
|
||
replaceable. So this gives us an evolution path. We can incrementally reduce the amount of django we use, replacing it with our own simpler
|
||
python that does only what we need.
|
||
<p>The separate functions within the framework form a "stack". These functions exist in all web application frameworks but in Django they are <a
|
||
href="https://docs.djangoproject.com/en/dev/misc/design-philosophies/">loosely coupled</a>.
|
||
<p id="stack"><b>The stack is:</b>
|
||
<ol>
|
||
<li>SQL database: <a href="https://docs.djangoproject.com/en/dev/topics/db/">mapping</a> to/from python objects and indexing/access routines for all the entries (sqlite, MySQL, MariaDB, postgres all work). This is where the multi-user synchronisation happens too.
|
||
<li>request/response (<a href="https://docs.djangoproject.com/en/dev/ref/request-response/">http GET/POST</a>) including <a href="https://docs.djangoproject.com/en/dev/topics/auth/default/#auth-web-requests">access control</a> and <a href="https://www.moesif.com/blog/engineering/middleware/What-Is-HTTP-Middleware/">security middleware</a>. We could never keep up with web security if we didn't use a well-supported system for this.
|
||
<li><a href="https://docs.djangoproject.com/en/dev/topics/http/urls/">URL mapping/dispatch</a> which matches a requested URL with a chunk of python code, and vice versa (declarative and bidrectional). "Cool URIs don't change."
|
||
<li><a href="https://docs.djangoproject.com/en/dev/topics/templates/">templates</a> which format the results of data queries into HTML pages or JSON data exports
|
||
</ol>
|
||
|
||
<p>See the <a href="https://docs.djangoproject.com/en/dev/misc/design-philosophies/">django design philosophy</a> on 'loose coupling and tight cohesion'. Note that having a URL dispatcher that supports
|
||
<a href="https://docs.djangoproject.com/en/dev/topics/http/urls/#s-reverse-resolution-of-urls">reverse resolution</a>
|
||
is important: it is a key reason why we need a framework and not just a mess of javascript. We have nearly 100 URL patterns.
|
||
We should try to reduce the number of distinct URLs perhaps, but they help document the structure too.
|
||
|
||
<h4>Other Cambridge student societies use Django</h4>
|
||
<p>CUYC, the yacht sailing club, has a website system 3-4x bigger than troggle which is used for booking weekly sailing trips and handles all their money and certification records. It is plugged (live) into PayPal. They have a turnover of over £50,000 a year. We don't know of other societies in this league (yet), but Django skills are not rare in Cambridge.
|
||
|
||
<h4 id="coding">More django coding tricks</h4>
|
||
<p>[This section, and the <a href="#3sent">3-sentence intro</a>, to go to another page ?]
|
||
<p>Much of our coding is still stuck in the early Django v1 era, before 2011. So many idioms in the code are not the best way of doing things these days. In particular there are powerful query optimisations now available that none of our code uses (yet):
|
||
<ul>
|
||
<li><a href="https://ctrlzblog.com/django-queryset-filter-15-examples/">.distinct()</a> - returns a list with no duplicated items, and many other clever filters
|
||
<li><a href="https://zerotobyte.com/how-to-use-django-select-related-and-prefetch-related/">select_related()</a> – creates INNER JOIN between tables
|
||
<li><a href="https://hakibenita.com/all-you-need-to-know-about-prefetching-in-django">prefetch_related()</a> – connects tables using Python (but queries both tables)
|
||
|
||
</ul>
|
||
and also much more about the manipulation of QuerySets:
|
||
<ul>
|
||
<li><a href="https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-create">bulk_create()</a> - just started using it in data imports in 2023.
|
||
</ul>
|
||
<h4>More refactoring still to do</h4>
|
||
<p>Some of the more bizarre data model structures are probably fossils from Django v0.6, e.g. the separate classes that join Entrances to Caves. We haven't got to the bottom of all these yet.
|
||
|
||
<h4>Django Forms</h4>
|
||
<p>Just don't. Django has several generations of quite different clever mechanisms to make creating HTML forms "easier". Yes, making them might be easier, but maintaining this opinionated stuff is a nightmare. Really don't.
|
||
<hr />
|
||
Go on to: <a href="trogdjangup.html">Troggle: updating Django</a><br />
|
||
Return to: <a href="trogintro.html">Troggle intro</a><br />
|
||
Troggle index:
|
||
<a href="trogindex.html">Index of all troggle documents</a><br />
|
||
<hr />
|
||
</body>
|
||
</html>
|