app_get_config(app_label).path as only way to get an app's path

54 views
Skip to first unread message

Christian González

unread,
Nov 10, 2019, 4:12:47 PM11/10/19
to django-developers
Hi all,

I recently found a problem - maybe I didn't get everything, but the docs
say that, if you want to get an app's path, you should use
get_app_config(app_label).path.

Now, passing the app_label is handy if you have few packages installed,
but it comes to name clashes if there are multiple packages with the
same label (but different names).

I happen to start a bigger project, and there are some packages
installed like "gdaps.frontend". Maybe one of my plugins later will be
named "medux.frontend". These two have a different name, but the same label.

Ok, I can simply do a

    from medux import frontend
    do_something_with(os.path.dirname(frontend.__file__))

But AppConfig.get_app_config() exactly should exist because I should NOT
do that.

How do I get the path of an app in a deterministic way, if there are
more than one packages with the same label? Is this a bug?

Thanks,

Christian

pEpkey.asc

Aymeric Augustin

unread,
Nov 11, 2019, 5:06:36 AM11/11/19
to django-d...@googlegroups.com
Hello Christian,

 if there are more than one packages with the same label?

Two apps cannot have the same label. One of them must be relabeled as described in https://docs.djangoproject.com/en/2.2/ref/applications/#django.apps.AppConfig.label.

If a pluggable app wants to access its own app config even if it was relabeled, there's no direct API to do so, but it's a one-liner:

from django.apps import apps
app_name = "gdaps.frontend"
app_config = [ac for ac in apps.get_app_configs() if ac.name == app_name][0]

This is pretty much how apps.is_installed(app_name) is implemented. There isn't a more efficient way to do this with the current implementation of django.apps.Apps.

Perhaps the API of django.apps.Apps could be improved to facilitate such use cases. At first sight, there are several options to consider:

- provide an apps.get_app_label(app_name) function that would do the translation from app_name to app_label
- accept either an app_label (e.g. "admin") or an app_name (e.g. "django.contrib.admin") in APIs that currently only accept an app_label
- etc.

It's been five years since Django 1.7 was released with new app registry. During this time, I haven't seen app_label conflicts or relabeling causing big problems in practice. (The only vaguely related case I've ever seen was someone who copy-pasted an app under a different name. This changed both the app_label and the app_name, so even relying on the app_name would fail in that case.)

I'd rather keep things simple here.

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.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/c8e6e354-7d02-835e-cd62-5d38102bd374%40nerdocs.at.
<pEpkey.asc>

Christian González

unread,
Nov 11, 2019, 2:46:40 PM11/11/19
to django-d...@googlegroups.com
 if there are more than one packages with the same label?

Two apps cannot have the same label. One of them must be relabeled as described in https://docs.djangoproject.com/en/2.2/ref/applications/#django.apps.AppConfig.label.

OMG. Are in great advantage - those who can read.


If a pluggable app wants to access its own app config even if it was relabeled, there's no direct API to do so, but it's a one-liner:

from django.apps import apps
app_name = "gdaps.frontend"
app_config = [ac for ac in apps.get_app_configs() if ac.name == app_name][0]

This is pretty much how apps.is_installed(app_name) is implemented. There isn't a more efficient way to do this with the current implementation of django.apps.Apps.

Perhaps the API of django.apps.Apps could be improved to facilitate such use cases. At first sight, there are several options to consider:

- provide an apps.get_app_label(app_name) function that would do the translation from app_name to app_label
- accept either an app_label (e.g. "admin") or an app_name (e.g. "django.contrib.admin") in APIs that currently only accept an app_label
- etc.

It's been five years since Django 1.7 was released with new app registry. During this time, I haven't seen app_label conflicts or relabeling causing big problems in practice. (The only vaguely related case I've ever seen was someone who copy-pasted an app under a different name. This changed both the app_label and the app_name, so even relying on the app_name would fail in that case.)

I'd rather keep things simple here.

Yes, understood. Not a big problem here. From a novice POV, I dumbly expected apps.get_app_config() to find the app when given a dotted name. So IMHO this would be a good approach.

Apps.get_apps_config() itself does a search for the name, and returns a message to the user ATM:

try:
    return self.app_configs[app_label]
except KeyError:
    message = "No installed app with label '%s'." % app_label
    for app_config in self.get_app_configs():
        if app_config.name == app_label:
            message += " Did you mean '%s'?" % app_config.label
            break

This could be a return statement too.

Just my 2c.

Christian

pEpkey.asc
Reply all
Reply to author
Forward
0 new messages