GDAPS

290 views
Skip to first unread message

Christian González

unread,
Jun 15, 2019, 12:14:52 PM6/15/19
to django-d...@googlegroups.com
Hi all,

sorry, I never managed to introduce myself properly to this mailing
list. Christian Gonzalez, more or less hobby programmer, MD as day job.
I maybe never will add something substantial to Django core itself, but
ATM "scratching my own itch" here:

Just wanted to say that I finished "Alpha state" for GDAPS - my "Generic
Django Apps Plugin System" which is an "enhancement" of Django's app
system, enabling Django to create "pluggable", extendable applications
with ease.

Just have a look at https://pypi.org/project/gdaps/

Thoughts, criticism welcome.

Christian

pEpkey.asc

Adam Johnson

unread,
Jun 16, 2019, 4:06:26 AM6/16/19
to django-d...@googlegroups.com
Hi Christian,

Welcome to the django developers list. I have had a quick look over GDAPS and have some comments and questions back for you:

* Your “homepage” link on PyPI is example.com. The usual thing to do here is link to your source host or docs. Set this as url in your setup.py.
* I see you list pretix as an inspiration - did you see Raphael have a talk at Djangocon Europe in April on this? https://youtu.be/QbitxAEEZjI It may be old news to you though if you’re familiar
* GPL can make your project hard to use, because depending on the lawyers it can be interpreted as having to make the website source code public. In the one dependency audit I went through, GPL and AGPL were disallowed and we had to strip a dependency or two because of this.
* What do you think are the implications for Django core? Is there anything Django could do better to support this and all the other plugin systems you’ve looked at? Also I’m totally sure you can contribute, it’s not scary and there is a lot of information on getting started! See 

Thanks,

Adam
--
You received this message because you are subscribed to the Google Groups "Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/d251dbee-bc4f-3325-a7bb-bb9d1f996cb1%40nerdocs.at.
For more options, visit https://groups.google.com/d/optout.
--
Adam

Christian González

unread,
Jun 16, 2019, 3:19:18 PM6/16/19
to django-d...@googlegroups.com
Am 16.06.19 um 10:06 schrieb Adam Johnson:
* Your “homepage” link on PyPI is example.com. The usual thing to do here is link to your source host or docs. Set this as url in your setup.py.
Sure. Forgot this when switching from setup.py to setup.cfg. Corrected, thanks.

* I see you list pretix as an inspiration - did you see Raphael have a talk at Djangocon Europe in April on this? https://youtu.be/QbitxAEEZjI It may be old news to you though if you’re familiar

Didn't know this talk, thanks. But I had an email conversation with him a while ago about that and he was the one who I learned a lot from about how to create GDAPS. Basically my implementation does not differ too much, and I even am considering using his "PretixPluginMeta" inner class in the AppConfig of GDAPS plugins too. I just think about other ways ATM - but I'm pretty sure I'll implement his way - in a more generic style.

It even could be that GDAPS plugins are so similar that Pretix *could* switch it's underlying plugin system to GDAPS without changing very much.

He did a really great job there and I never would be able to do this on my own, without the insights he gave me to Pretix. Same goes for PyUtilib.

* GPL can make your project hard to use, because depending on the lawyers it can be interpreted as having to make the website source code public. In the one dependency audit I went through, GPL and AGPL were disallowed and we had to strip a dependency or two because of this.

Yes, you are right too. This was another too fast shot - I'd like to release my project which is using GDAPS under the GPL/AGPL later. GDAPS is a library, and here the GPL doesn't help much. I need to think about it a bit, a little part of the code is from PyUtilib (which is BSD), and a bit copied from Graphene-Django (which is MIT). So maybe I'll switch to BSD too. Recommendations here for Django libraries, or specially GDAPS?

* What do you think are the implications for Django core? Is there anything Django could do better to support this and all the other plugin systems you’ve looked at? Also I’m totally sure you can contribute, it’s not scary and there is a lot of information on getting started! See 

Yes, I'll have a deeper look at the contributing guidelines.
The most parts where I had to struggle within Django were:

* The settings, to let each module provide it's own setting. There is no standardized way of having settings saved. I borrowed the graphene-django way - which had copied it from DRF ;-)

* Django doesn't allow to easily add apps to the running server when already started. Even adding apps to INSTALLED_APPS after loading Django is impossible, it has to be done within the setup process - I solved that using a Pluginmanager method (find_plugins) which is called after declaring INSTALLED_APPS in settings.ps, and which returns an INSTALLED_APPS compatible array which can be merged into INSTALLED_APPS. This method is certainly not able to call DB commands in that early startup point of time.
So what I initially planned, downloading apps from a connected "app store" for my application, installing it "on the fly" (including makemigrations/migrate paths) and hooking in the plugin into the running process is not possible in Django.

I don't have a big problem here, as installing a plugin ATM in GDAPS is just (for projects without SPA/frontend support):

stop server
pip install fooplugin
./manage.py makemigrations
./manage.py migrate
start server

which is perfectly ok for what I need.

* URL routing was easy to integrate - the only thing which is remaining IMHO is - django does not help to "weigh" the rules. But this is a thing I want to implement in GDAPS - to give plugin apps the possibility to add a "weight" to URL paths so they are "ordered" in a more deterministic way.
I just created a ticket where I described that a bit: https://gitlab.com/nerdocs/gdaps/issues/4

Same could go to the INSTALLED_APPS ordering. A "weight" ordering is not ideal here, I think that a dependency resolution system would be much better here. Here Django could help a bit - Django apps are depending on other apps, declared in setup.py or setup.cfg. If this meta information would be available to Django (or GDAPS), the loading of apps (GDAPS plugins) could be at least done automatically in a way that dependant apps are loaded after their dependencies.

So far... much to do.
I hope earth is going to spin slower soon, so a day gets more than 24h. ;-)

Christian
pEpkey.asc

Curtis Maloney

unread,
Jun 16, 2019, 8:19:02 PM6/16/19
to django-d...@googlegroups.com
[forgive me for typing as I think... but sometimes it's the best way to
think ;) ]

On 6/17/19 5:19 AM, Christian González wrote:
> Am 16.06.19 um 10:06 schrieb Adam Johnson:
>> * What do you think are the implications for Django core? Is there
>> anything Django could do better to support this and all the other
>> plugin systems you’ve looked at? Also I’m totally sure you can
>> contribute, it’s not scary and there is a lot of information on
>> getting started! See
>> https://docs.djangoproject.com/en/dev/internals/contributing/
>
> Yes, I'll have a deeper look at the contributing guidelines.
> The most parts where I had to struggle within Django were:
>
> * The settings, to let each module provide it's own setting. There is no
> standardized way of having settings saved. I borrowed the
> graphene-django way - which had copied it from DRF ;-)

I've given some thought to this over the years, and what I think we've
somehow missed in settings until now is ... Namespaces!

Whilst we have namespace-by-prefix (CACHE_*) and namespace-by-dict
(DATABASES = {} ) when it comes to plugins having their own declared
settings, we may want to move to something a little more formal.

Any plugin or app ought be able to declare its own settings and their
defaults. And ISTM the "obvious" place to do this is in their AppConfig

Except, that may be too late, since we may want/need the settings before
apps are loaded?

So the alternative is for a plugin to declare in its entry points a
reference to its settings declaration. This way, all 3rd party settings
can be gathered, vetted, and applied before having to scan the
INSTALLED_APPS list.

Now what we'll need is a way to avoid namespace clashes, and a
dev-friendly way to update these settings in settings.py

--
Curtis

Benny

unread,
Jun 16, 2019, 9:42:18 PM6/16/19
to django-d...@googlegroups.com
Long time lurker first time poster; could this possibly be addressed with something along the lines of SECRET_KEY? It seems to me that no more of a namespace would be needed than a uniquely identifying hash per app/module. Not so much in settings or app_config as __init__, maybe?

Hi,
Benny
> --
> You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
> To post to this group, send email to django-d...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-developers.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/d8cc1a37-b8ae-3a0c-021b-92ec6f7e5701%40tinbrain.net.

Christian González

unread,
Jun 17, 2019, 3:47:41 AM6/17/19
to django-d...@googlegroups.com

> I've given some thought to this over the years, and what I think we've
> somehow missed in settings until now is ... Namespaces!

I can second this from my POV, having "evaluated" a few plugin systems now.


> Any plugin or app ought be able to declare its own settings and their
> defaults. And ISTM the "obvious" place to do this is in their AppConfig
>
> Except, that may be too late, since we may want/need the settings
> before apps are loaded?
>
> So the alternative is for a plugin to declare in its entry points a
> reference to its settings declaration. This way, all 3rd party
> settings can be gathered, vetted, and applied before having to scan
> the INSTALLED_APPS list.

I want to separate these things: Yes, AppConfig is too late, as the
settings.py is already scanned, and INSTALLED_APPS are determined.
That's because Django works this way. I don't recommend Django to
completely change its way of loading apps.
In GDAPS there are 2 ways of adding apps/plugins: 1. simply add it to
INSTALLED_APPS. A GDAPS plugin ins a normal Django app. 2. via
setuptools entry point, like pretix. I therefore added my Pluginmanager
hook, also like pretix. It just finds the plugins and adds them to
INSTALLED_APPS.
But here it is too late. settings.py continues, and *afterwords* all the
apps are scanned for their settings. you can't override them again in
settings.py after that.

What would IMHO clean this problem, would be moving INSTALLED_APPS
outside of settings.py (maybe in a declarative way: yml, cfg file etc.).
Then Django could scan this list, load apps (or do whatever it needs,
scan metadata, check for compatibility, etc.), load their settings, and
*afterwords* run the main settings.py to eventually override some of the
apps' settings globally. This could even be coded with backwards
compatibility, e.g. if installed_apps.cfg is present, use that (and
disallow INSTALLED_APPS in settings.py),  else fall back to
settings.INSTALLED_APPS.

It wouldn't be necessary to make a setuptools entry point for app/plugin
settings. The entry point I would recommend is a "settings.py" for each
app - automatically namespaced or better, with a NAMESPACE = "fooplugin"
- which would enable having 2 plugins using the same namespace (think of
"sub-plugins" of one bigger plugin).


> Now what we'll need is a way to avoid namespace clashes, and a
> dev-friendly way to update these settings in settings.py
I would definitely *allow* namespace clashes, as explained above. Like
in partial classes. A "Textprinter" plugin could have 3rdparty
sub-plugins, which could use the same namespace (HTMLProviderPlugin,
MarkdownProviderPlugin etc.)
pEpkey.asc

Curtis Maloney

unread,
Jun 17, 2019, 4:37:14 AM6/17/19
to django-d...@googlegroups.com
On 6/17/19 5:47 PM, Christian González wrote:
>
>> I've given some thought to this over the years, and what I think we've
>> somehow missed in settings until now is ... Namespaces!
>
> I can second this from my POV, having "evaluated" a few plugin systems now.
>
>
>> Any plugin or app ought be able to declare its own settings and their
>> defaults. And ISTM the "obvious" place to do this is in their AppConfig
>>
>> Except, that may be too late, since we may want/need the settings
>> before apps are loaded?
>>
>> So the alternative is for a plugin to declare in its entry points a
>> reference to its settings declaration. This way, all 3rd party
>> settings can be gathered, vetted, and applied before having to scan
>> the INSTALLED_APPS list.
>
> I want to separate these things: Yes, AppConfig is too late, as the
> settings.py is already scanned, and INSTALLED_APPS are determined.
> That's because Django works this way. I don't recommend Django to
> completely change its way of loading apps.

> In GDAPS there are 2 ways of adding apps/plugins: 1. simply add it to
> INSTALLED_APPS. A GDAPS plugin ins a normal Django app. 2. via
> setuptools entry point, like pretix. I therefore added my Pluginmanager
> hook, also like pretix. It just finds the plugins and adds them to
> INSTALLED_APPS.

> But here it is too late. settings.py continues, and *afterwords* all the
> apps are scanned for their settings. you can't override them again in
> settings.py after that.

I'm a little unclear here.

Is it too late because you want to be able to exclude settings from
packages that are installed but you don't want "active" in the project?

That you only want 3rd party "settings contributing" plugins to be
activated when selected?

In which case, doesn't it make more sense to include a plugins.cfg to be
processed _before_ settings.py to decide? And if handled well, I expect
only an exclusion list may be required [but an inclusion list would be
safer].

> What would IMHO clean this problem, would be moving INSTALLED_APPS
> outside of settings.py (maybe in a declarative way: yml, cfg file etc.).
> Then Django could scan this list, load apps (or do whatever it needs,
> scan metadata, check for compatibility, etc.), load their settings, and
> *afterwords* run the main settings.py to eventually override some of the
> apps' settings globally. This could even be coded with backwards
> compatibility, e.g. if installed_apps.cfg is present, use that (and
> disallow INSTALLED_APPS in settings.py),  else fall back to
> settings.INSTALLED_APPS.

> It wouldn't be necessary to make a setuptools entry point for app/plugin
> settings. The entry point I would recommend is a "settings.py" for each
> app - automatically namespaced or better, with a NAMESPACE = "fooplugin"
> - which would enable having 2 plugins using the same namespace (think of
> "sub-plugins" of one bigger plugin).

Ah, I think I see now. You want INSTALLED_APPS to be the definitive
truth of all apps _and_ plugins. So it's not possible to have a plugin
that's not also an app?

Sub-plugins opens up the can of works that is dependency resolution.

>> Now what we'll need is a way to avoid namespace clashes, and a
>> dev-friendly way to update these settings in settings.py
> I would definitely *allow* namespace clashes, as explained above. Like
> in partial classes. A "Textprinter" plugin could have 3rdparty
> sub-plugins, which could use the same namespace (HTMLProviderPlugin,
> MarkdownProviderPlugin etc.)

Yes, I did consider this. I think it's valid that a plugin may override
another plugins defaults.

But in the end, the projects settings.py should be final.

--
Curtis

Christian González

unread,
Jun 18, 2019, 9:30:44 AM6/18/19
to django-d...@googlegroups.com
But here it is too late. settings.py continues, and *afterwords* all the
apps are scanned for their settings. you can't override them again in
settings.py after that.
I'm a little unclear here.

Is it too late because you want to be able to exclude settings from
packages that are installed but you don't want "active" in the project?

The main problem is that settings are code in Django, and not
declarative. You have to *import* them, you don't parse them.

I did that similar to Pretix (mine isn't finished yet): you have to
differ between "installed" and "active".  Packages which are installed
could have a "switch" (which has to be  a changeable, cached, database
state) where to activate/deactivate it. A deactivated plugin is omitted
when itering over its implementations, and doesn't emit signals.

That's what you really want, I suppose?

I think settings - if they are really just *declarative settings*
(without code) - would be nice to be parsed *before* loading apps. But
Django uses .py files as settings, which is a blessing and a course.
There can be conditionals and code in a settings file, which is cool,
but leads to problems. Just to not get me wrong: I don't suggest to
change Django settings model here - .py files are ok IMHO. But We have
to deal with that somehow.


That you only want 3rd party "settings contributing" plugins to be
activated when selected?

In which case, doesn't it make more sense to include a plugins.cfg to
be processed _before_ settings.py to decide?  And if handled well, I
expect only an exclusion list may be required [but an inclusion list
would be safer].
Definitely. That's the main reason I had liked to implement a
declarative plugin spec file with plugin metadata (and maybe default
settings?) instead of having plugin Metadata in the AppConfig as
subclass - like Raphael did in Pretix. This is a cool and easy approach,
but you *have to* import the plugin for getting the metadata - and
plugin code has already run then. It's too late to decide: No I don't
want that plugin running.

But in the end I decided, that from a security POV, it makes no
difference. If you have a plugin already on your server, it doesn't
matter if you have a settings.cfg or pluginspec.cfg file to parse. You
have to trust the plugin anyway when you run it's main entry point later.

And from that POV, using Python code (= a class) as metadata or
settings, is ok, so most certainly I will implement Pretix' Metadata
system into GDAPS as well, additionally being most compatible with Pretix.

It wouldn't be necessary to make a setuptools entry point for app/plugin
settings. The entry point I would recommend is a "settings.py" for each
app - automatically namespaced or better, with a NAMESPACE = "fooplugin"
- which would enable having 2 plugins using the same namespace (think of
"sub-plugins" of one bigger plugin).
Ah, I think I see now.  You want INSTALLED_APPS to be the definitive
truth of all apps _and_ plugins. So it's not possible to have a plugin
that's not also an app?
That was my intention, yes. Because else I would need another entry
point system, Django apps are fine except to the fact that they are not
pluggable.
That's the perfect combination IMHO: Use Django apps as "reusable" apps
like DRF etc, like a Mixin which fulfills the same purpose in different
contexts, applications etc., and use Django apps that are enhanced as
GDAPS plugins to extend *one* single Django application with plugins
that could be written by others.

That's what Raphael said in his DjangoCon talk.

Sub-plugins opens up the can of works that is dependency resolution.
No, this can is already opened when loading plugins/apps via setuptools
entry points. I called "Sub-plugins" the ones that live under the same
"namespace", if that will be an option.


Now what we'll need is a way to avoid namespace clashes, and a
dev-friendly way to update these settings in settings.py
I would definitely *allow* namespace clashes, as explained above. Like
in partial classes. A "Textprinter" plugin could have 3rdparty
sub-plugins, which could use the same namespace (HTMLProviderPlugin,
MarkdownProviderPlugin etc.)
Yes, I did consider this. I think it's valid that a plugin may
override another plugins defaults.
Definitely, but only, if it declares a (at least weak) dependency on
that other plugin. PluginA could "support" plugins like PluginB and C
*if* they are present, and could then override their defaults. I e.g.
decided to implement a "core" plugin - like QtCreator did - to make live
easier for versioning - plugins relaying on "CorePlugin>=2.3.5" can't be
installed then when CorePlugin is 2.0.0. So Core is like any other plugin.
And so all plugins depend on Core plugin and could override its
defaults. Next problem here is, what if 2 plugins override the default
of a third one. The last in the loading row wins then.

There are MANY things to consider - but I decided to just start off, and
look where the journey brings me.

But in the end, the projects settings.py should be final.
Yes.

Christian

pEpkey.asc

Christian González

unread,
Jun 19, 2019, 5:13:04 PM6/19/19
to django-d...@googlegroups.com

I'd like to ask another question concerning plugin apps, and hoping your deeper knowledge about Django internals helps here...

I'm implementing the plugin Metadata for GDAPS plugins ATM, and am a bit concerned wether to implement a construct like the Pretix system or not.

Pretix uses AppConfig classes, and creates a inner PretixPluginMeta classs where it sums up all the information it needs. It's easy then to  walk all apps and filter out the ones that have a PretixPluginsMeta - and get their data out.

class PaypalApp(PluginConfig):
    name = 'pretix_paypal'
    verbose_name = _("PayPal")

    class PretixPluginMeta:
        name = _("PayPal")
        author = _("the pretix team")
        version = '1.0.0'
        visible = True
        restricted = False
        description = _("This plugin allows you to receive payments via PayPal")
        compatibility = "pretix>=2.7.0"

What I need for a good plugin life cycle are methods, callbacks that are called when a plugin is "installed" = run the first time, methods for enabling/disabling etc.

The easiest way would be implementing these methods within the AppConfig subclass.

I asked myself why is there a PluginMeta needed? Can't I add those data attributes directly to AppConfig?

So my question on you all is: Is it a good idea to merge those data deeply with tha AppConfig object? I mean, as a plugin in my sense is more or less the same as an app, it won't matter. But deeply inside, I feel that there is something wrong done. Separate concerns should not me mixed - and I don't know what you want to implement in Django's future into AppConfig. Maybe there could be conflicts.

Another way would be implementing the methods too into the PluginMeta object.

May I ask for your opinions here?

And a second question: The DJango docs say, that it's not recommended to use "default_app_config". But in each and every example, even in the tutorials and the Django boilerplate code of "./manage.py startproject foo" are NO Appconfigs addressed in INSTALLED_APPS. Nobody does this, right?

How "obligate" is this recommendation, when noone uses it? Should this be kept?

Thanks,

Christian

pEpkey.asc

Curtis Maloney

unread,
Jun 19, 2019, 9:18:35 PM6/19/19
to django-d...@googlegroups.com
On 6/20/19 7:12 AM, Christian González wrote:
> What I need for a good plugin life cycle are methods, callbacks that are
> called when a plugin is "installed" = run the first time, methods for
> enabling/disabling etc.
>
> The easiest way would be implementing these methods within the AppConfig
> subclass.
>
> I asked myself why is there a PluginMeta needed? Can't I add those data
> attributes directly to AppConfig?
>
> So my question on you all is: Is it a good idea to merge those data
> deeply with tha AppConfig object? I mean, as a plugin in my sense is
> more or less the same as an app, it won't matter. But deeply inside, I
> feel that there is something wrong done. Separate concerns should not me
> mixed - and I don't know what you want to implement in Django's future
> into AppConfig. Maybe there could be conflicts.
>
> Another way would be implementing the methods too into the PluginMeta
> object.
>
> May I ask for your opinions here?

I would likely keep this interface isolated from the app config, to
prevent future name clashes.

> And a second question: The DJango docs say, that it's not recommended to
> use "default_app_config". But in each and every example, even in the
> tutorials and the Django boilerplate code of "./manage.py startproject
> foo" are NO Appconfigs addressed in INSTALLED_APPS. Nobody does this, right?
>
> How "obligate" is this recommendation, when noone uses it? Should this
> be kept?

I think it's most likely there as a legacy state, in order to reduce the
burden of upgrading.

I do agree it would be better if we abide by our own recommendations.

--
Curtis

Christian González

unread,
Jan 5, 2020, 8:30:18 AM1/5/20
to django-d...@googlegroups.com


Am 20.06.19 um 03:18 schrieb Curtis Maloney:

And a second question: The DJango docs say, that it's not recommended to use "default_app_config". But in each and every example, even in the tutorials and the Django boilerplate code of "./manage.py startproject foo" are NO Appconfigs addressed in INSTALLED_APPS. Nobody does this, right?

How "obligate" is this recommendation, when noone uses it? Should this be kept?

I think it's most likely there as a legacy state, in order to reduce the burden of upgrading.

I do agree it would be better if we abide by our own recommendations.

But is this really necessary?

When you look at your documentation, like the tutorial in https://docs.djangoproject.com/en/3.0/intro/reusable-apps/ - "Quick start" - you use

    INSTALLED_APPS = [
        ...
        'polls',
    ]

It should be 'polls.apps.PollsConfig'
And to be honest - does this really make sense to urge people - writing more code to satisfy the framework?

I tried to follow that rule in my own framework, but it's like driving 49,99 km/h in 50 speed limit on the street, when everyone else drives 55. Even Google allows it's self driving cars to drive faster than the limit by 10% in some cases ;-)

What I mean is: Why don't you drop that recommendation - when noone is using it - more than one AppConfigs still *are* possible, even when there is a default.

Christian


-- 
Dr. Christian González
https://nerdocs.at
pEpkey.asc

MUGALIM ONLINE

unread,
Jan 5, 2020, 8:51:00 AM1/5/20
to django-d...@googlegroups.com
how to use oracle in django 

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.

Aymeric Augustin

unread,
Jan 8, 2020, 4:39:57 PM1/8/20
to django-d...@googlegroups.com
Hello Christian,

On 5 Jan 2020, at 14:30, Christian González <christian...@nerdocs.at> wrote:

And to be honest - does this really make sense to urge people - writing more code to satisfy the framework?

What I mean is: Why don't you drop that recommendation - when noone is using it - more than one AppConfigs still *are* possible, even when there is a default

The original intent was to make configuration explicit by having settings.py reference directly the target AppConfig class.

- When you write MIDDLEWARE = ["polls"], do you expect Django to enable "polls.middleware.PollsMiddleware"?
- When you write INSTALLED_APPS = ["polls"], do you expect Django to enable "polls.apps.PollsAppConfig"?

Many readers of this mailing list will answer "no" and "yes" respectively. I think the answer to both should be "no", according to Django's design philosophy. (If you're about to argue that an application can provide more than one middleware — I'm aware of this and I know you understood my point anyway.)

Even though the extra level of indirection via default_app_config exists only for backwards-compatibility, everyone seems to be happy with it. Perhaps it's time to be pragmatic and admit I made the wrong call.

If we're reversing course, giving up on explicitness and going for magic, we could embrace that decision fully: import the "apps" submodule inside each application; if it exists and it defines exactly one AppConfig subclass, use that as the config for this app. Then app authors can stop littering their __init__.py files with default_app_config.

Best regards,

-- 
Aymeric.

Christian González

unread,
Jan 10, 2020, 8:18:59 AM1/10/20
to django-d...@googlegroups.com


Am 08.01.20 um 22:39 schrieb Aymeric Augustin:
The original intent was to make configuration explicit by having settings.py reference directly the target AppConfig class.

- When you write MIDDLEWARE = ["polls"], do you expect Django to enable "polls.middleware.PollsMiddleware"?
- When you write INSTALLED_APPS = ["polls"], do you expect Django to enable "polls.apps.PollsAppConfig"?

Many readers of this mailing list will answer "no" and "yes" respectively. I think the answer to both should be "no", according to Django's design philosophy. (If you're about to argue that an application can provide more than one middleware — I'm aware of this and I know you understood my point anyway.)
Yes, that's exactly what I wanted to state.
[...]


If we're reversing course, giving up on explicitness and going for magic, we could embrace that decision fully: import the "apps" submodule inside each application; if it exists and it defines exactly one AppConfig subclass, use that as the config for this app. Then app authors can stop littering their __init__.py files with default_app_config.

That would be perfect IMHO. One could consider restricting it to the same-named subclass like the app itself, so the app "foo" would need to have "FooConfig" as default.

I'm aware that this violates the 2nd "Zen of Python" principle "Explicit is better than implicit". and "Special cases aren't special enough to break the rules." - but the next one says: "Although practicality beats purity."

Yes, too much "magic" leads to a system where half of it uses magic, and the other half not - so it's not predictable for the developer what a certain line does.

But exactly in this part I think that having a "sane default" - in the sense of app loading using by using the app name only - is ok.

I would bet that the vast majority of apps don't have two AppConfigs.
And to urge all devs to use the more elaborative AppConfig line in INSTALLED_APPS, just to make such special cases (and THESE are the special cases!) are possible, is wrong IMHO.

Let it be easy - even the variable says INSTALLED_APPS, not INSTALLED_CONFIGS. And let there be the possibility to declare other AppConfigs on demand.

Aymeric Augustin

unread,
Jan 12, 2020, 3:43:10 PM1/12/20
to django-d...@googlegroups.com
Hello,

I created a PR for this: https://github.com/django/django/pull/12310

I'd love to get some feedback on the design before I polish the patch.

Best regards,

-- 
Aymeric.



--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.

Christian González

unread,
Jan 13, 2020, 5:03:40 PM1/13/20
to django-d...@googlegroups.com

Eh, sorry if I misunderstand - but adding a "default = true" line to an AppConfig is the same as addign default_app_config = "foo.apps.FooConfig".

A few things that came to my mind when reading the code:

* You check if there is only one AppConfig available (https://github.com/django/django/pull/12310/commits/6a4ee2d02477cac1fa67708ceefda2ffd56bbf96#diff-239ff7e40a4b9921b462471882a575f6R111) and if so, this one is used - that's perfect IMHO.

* But what if 2 AppConfigs have "default = true" ? Then line #139+ is run, and silently the default app config class is used - none of the two ones. Maybe an error message would be better. default=true should only be valid once!

Best regards,

Christian

Am 12.01.20 um 21:42 schrieb Aymeric Augustin:
pEpkey.asc

Christian González

unread,
Jan 13, 2020, 5:05:07 PM1/13/20
to django-d...@googlegroups.com

Oh, sorry, I just saw that this is discussed (andanswered) in the PR.

Am 13.01.20 um 23:03 schrieb Christian González:
pEpkey.asc

Aymeric Augustin

unread,
Jan 14, 2020, 2:57:02 PM1/14/20
to django-d...@googlegroups.com
Hello Christian,

Regarding your first point, adding "default = True" to 1% of apps in a non-empty file seems better than adding default_app_config = "foo.apps.FooConfig" to 99% of apps in an otherwise empty file (usually). You can see the effect in https://github.com/django/django/pull/12310/commits/91cc52ed55dd1ec6cc05b9aa2d9a48aff3cdf87b.

Best regards,

-- 
Aymeric.



Raffaele Salmaso

unread,
Jan 14, 2020, 4:54:07 PM1/14/20
to django-d...@googlegroups.com
Hi, just noted this discussion...

On Sun, Jan 12, 2020 at 9:42 PM Aymeric Augustin <aymeric....@polytechnique.org> wrote:
Hello
I created a PR for this: https://github.com/django/django/pull/12310

I'd love to get some feedback on the design before I polish the patch.
I've left a comment in PR, but maybe here is more appropriate for general discussion:
please, don't add other magic or special cases...
I'm for deprecate and remove the default_app_config and have only one way to add an application.

Thanks

--
Reply all
Reply to author
Forward
0 new messages