您可以给Django应用指定一个冗长的名称以供整个管理员使用吗?

问题:您可以给Django应用指定一个冗长的名称以供整个管理员使用吗?

您可以使用为字段和模型提供Django管理员中显示的详细名称的相同方式,可以为应用程序自定义名称吗?

In the same way that you can give fields and models verbose names that appear in the Django admin, can you give an app a custom name?


回答 0

Django 1.8以上

根据1.8文档(和当前文档),

新应用程序应避免使用default_app_config。相反,它们应要求在中AppConfig显式配置指向适当子类的虚线路径INSTALLED_APPS

例:

INSTALLED_APPS = [
    # ...snip...
    'yourapp.apps.YourAppConfig',
]

然后AppConfig,如下所示更改您的。

的Django 1.7

正如rhunwicks对OP的评论所言,自Django 1.7起,这已成为可能

取自文档

# in yourapp/apps.py
from django.apps import AppConfig

class YourAppConfig(AppConfig):
    name = 'yourapp'
    verbose_name = 'Fancy Title'

然后将default_app_config变量设置为YourAppConfig

# in yourapp/__init__.py
default_app_config = 'yourapp.apps.YourAppConfig'

Django 1.7之前的版本

您可以通过在模型定义中定义app_label来给应用程序自定义名称。但是,随着django构建管理页面时,它将按模型的app_label哈希模型,因此,如果希望它们出现在一个应用程序中,则必须在应用程序的所有模型中定义此名称。

class MyModel(models.Model):
        pass
    class Meta:
        app_label = 'My APP name'

Django 1.8+

Per the 1.8 docs (and current docs),

New applications should avoid default_app_config. Instead they should require the dotted path to the appropriate AppConfig subclass to be configured explicitly in INSTALLED_APPS.

Example:

INSTALLED_APPS = [
    # ...snip...
    'yourapp.apps.YourAppConfig',
]

Then alter your AppConfig as listed below.

Django 1.7

As stated by rhunwicks’ comment to OP, this is now possible out of the box since Django 1.7

Taken from the docs:

# in yourapp/apps.py
from django.apps import AppConfig

class YourAppConfig(AppConfig):
    name = 'yourapp'
    verbose_name = 'Fancy Title'

then set the default_app_config variable to YourAppConfig

# in yourapp/__init__.py
default_app_config = 'yourapp.apps.YourAppConfig'

Prior to Django 1.7

You can give your application a custom name by defining app_label in your model definition. But as django builds the admin page it will hash models by their app_label, so if you want them to appear in one application, you have to define this name in all models of your application.

class MyModel(models.Model):
        pass
    class Meta:
        app_label = 'My APP name'

回答 1

正如rhunwicks对OP的评论所言,自Django 1.7起,这已成为可能

取自文档

# in yourapp/apps.py
from django.apps import AppConfig

class YourAppConfig(AppConfig):
    name = 'yourapp'
    verbose_name = 'Fancy Title'

然后将default_app_config变量设置为YourAppConfig

# in yourapp/__init__.py
default_app_config = 'yourapp.apps.YourAppConfig'

As stated by rhunwicks’ comment to OP, this is now possible out of the box since Django 1.7

Taken from the docs:

# in yourapp/apps.py
from django.apps import AppConfig

class YourAppConfig(AppConfig):
    name = 'yourapp'
    verbose_name = 'Fancy Title'

then set the default_app_config variable to YourAppConfig

# in yourapp/__init__.py
default_app_config = 'yourapp.apps.YourAppConfig'

回答 2

如果应用程序中有多个模型,则只需使用元信息创建一个模型,然后为所有模型创建该类的子类。

class MyAppModel(models.Model):
    class Meta:
        app_label = 'My App Label'
        abstract = True

class Category(MyAppModel):
     name = models.CharField(max_length=50)

If you have more than one model in the app just create a model with the Meta information and create subclasses of that class for all your models.

class MyAppModel(models.Model):
    class Meta:
        app_label = 'My App Label'
        abstract = True

class Category(MyAppModel):
     name = models.CharField(max_length=50)

回答 3

给他们一个verbose_name属性。

不要抱有希望。您还需要将索引视图从django.contrib.admin.sites复制到您自己的ProjectAdminSite视图中,并将其包含在您自己的自定义管理实例中:

class ProjectAdminSite(AdminSite):
    def index(self, request, extra_context=None):
        copied stuff here...

admin.site = ProjectAdminSite()

然后调整复制的视图,以便它使用您的verbose_name属性作为应用程序的标签。

我通过在复制的视图中添加如下内容来完成此操作:

        try:
            app_name = model_admin.verbose_name
        except AttributeError:
            app_name = app_label

在调整索引视图时,为什么也不要添加“ order”属性。

Give them a verbose_name property.

Don’t get your hopes up. You will also need to copy the index view from django.contrib.admin.sites into your own ProjectAdminSite view and include it in your own custom admin instance:

class ProjectAdminSite(AdminSite):
    def index(self, request, extra_context=None):
        copied stuff here...

admin.site = ProjectAdminSite()

then tweak the copied view so that it uses your verbose_name property as the label for the app.

I did it by adding something a bit like this to the copied view:

        try:
            app_name = model_admin.verbose_name
        except AttributeError:
            app_name = app_label

While you are tweaking the index view why not add an ‘order’ property too.


回答 4

好吧,我启动了一个名为todo的应用程序,现在决定将其命名为Tasks。问题是我的表中已经有数据,因此我的解决方法如下。放入models.py:

    class Meta:
       app_label = 'Tasks'
       db_table = 'mytodo_todo'

希望能帮助到你。

Well I started an app called todo and have now decided I want it to be named Tasks. The problem is that I already have data within my table so my work around was as follows. Placed into the models.py:

    class Meta:
       app_label = 'Tasks'
       db_table = 'mytodo_todo'

Hope it helps.


回答 5

对于Django 1.4(尚未发布,但主干非常稳定),可以使用以下方法。它依赖于AdminSite现在返回TemplateResponse的事实,您可以在呈现它之前对其进行更改。

在这里,我们做了一些Monkey修补来插入我们的行为,如果您使用自定义AdminSite子类,则可以避免这种情况。

from functools import wraps
def rename_app_list(func):
    m = {'Sites': 'Web sites',
         'Your_app_label': 'Nicer app label',
    }

    @wraps(func)
    def _wrapper(*args, **kwargs):
        response = func(*args, **kwargs)
        app_list = response.context_data.get('app_list')

        if app_list is not None:
            for a in app_list:
                name = a['name']
                a['name'] = m.get(name, name)
        title = response.context_data.get('title')
        if title is not None:
            app_label = title.split(' ')[0]
            if app_label in m:
                response.context_data['title'] = "%s administration" % m[app_label]
        return response
    return _wrapper

admin.site.__class__.index = rename_app_list(admin.site.__class__.index)
admin.site.__class__.app_index = rename_app_list(admin.site.__class__.app_index)

这样可以修复索引和app_index视图。它并不能解决所有其他管理员视图中的面包屑。

For Django 1.4 (not yet released, but trunk is pretty stable), you can use the following method. It relies on the fact that AdminSite now returns a TemplateResponse, which you can alter before it is rendered.

Here, we do a small bit of monkey patching to insert our behaviour, which can be avoided if you use a custom AdminSite subclass.

from functools import wraps
def rename_app_list(func):
    m = {'Sites': 'Web sites',
         'Your_app_label': 'Nicer app label',
    }

    @wraps(func)
    def _wrapper(*args, **kwargs):
        response = func(*args, **kwargs)
        app_list = response.context_data.get('app_list')

        if app_list is not None:
            for a in app_list:
                name = a['name']
                a['name'] = m.get(name, name)
        title = response.context_data.get('title')
        if title is not None:
            app_label = title.split(' ')[0]
            if app_label in m:
                response.context_data['title'] = "%s administration" % m[app_label]
        return response
    return _wrapper

admin.site.__class__.index = rename_app_list(admin.site.__class__.index)
admin.site.__class__.app_index = rename_app_list(admin.site.__class__.app_index)

This fixes the index and the app_index views. It doesn’t fix the bread crumbs in all other admin views.


回答 6

首先,您需要apps.py在appfolder上创建一个像这样的文件:

# appName/apps.py

# -*- coding: utf-8 -*-             
from django.apps import AppConfig

class AppNameConfig(AppConfig):
    name = 'appName'
    verbose_name = "app Custom Name"

要默认加载此AppConfig子类:

# appName/__init__.py
default_app_config = 'appName.apps.AppNameConfig'

是最好的方法。在Django 1.7上测试

对于西班牙语有问题的人

此代码在python2脚本上启用utf-8兼容性

# -*- coding: utf-8 -*-

First you need to create a apps.py file like this on your appfolder:

# appName/apps.py

# -*- coding: utf-8 -*-             
from django.apps import AppConfig

class AppNameConfig(AppConfig):
    name = 'appName'
    verbose_name = "app Custom Name"

To load this AppConfig subclass by default:

# appName/__init__.py
default_app_config = 'appName.apps.AppNameConfig'

Is the best way to do. tested on Django 1.7

For the person who had problems with the Spanish

This code enable the utf-8 compatibility on python2 scripts

# -*- coding: utf-8 -*-

回答 7

否,但是您可以复制管理模板并在其中定义应用程序名称。

No, but you can copy admin template and define app name there.


回答 8

可以完成不需要任何迁移的hack。摘自Ionel的博客,信誉归功于他:http : //blog.ionelmc.ro/2011/06/24/custom-app-names-in-the-django-admin/

还有一个票证应该在Django 1.7 https://code.djangoproject.com/ticket/3591中修复

“”

假设您有一个这样的模型:

class Stuff(models.Model):
    class Meta:
        verbose_name = u'The stuff'
        verbose_name_plural = u'The bunch of stuff'

您有verbose_name,但是您也想自定义app_label以便在admin中进行不同的显示。不幸的是,有一些任意字符串(带空格)是行不通的,而且无论如何也不能显示。

原来,管理员使用app_label。title()进行显示,因此我们可以做些改动:str子类,带有重写的title方法:

class string_with_title(str):
    def __new__(cls, value, title):
        instance = str.__new__(cls, value)
        instance._title = title
        return instance

    def title(self):
        return self._title

    __copy__ = lambda self: self
    __deepcopy__ = lambda self, memodict: self

现在我们可以有这样的模型:

class Stuff(models.Model):
    class Meta:
        app_label = string_with_title("stuffapp", "The stuff box")
        # 'stuffapp' is the name of the django app
        verbose_name = 'The stuff'
        verbose_name_plural = 'The bunch of stuff'

管理员将显示“填充框”作为应用名称。

“”

There is a hack that can be done that does not require any migrations. Taken from Ionel’s blog and credit goes to him: http://blog.ionelmc.ro/2011/06/24/custom-app-names-in-the-django-admin/

There is also a ticket for this that should be fixed in Django 1.7 https://code.djangoproject.com/ticket/3591

“””

Suppose you have a model like this:

class Stuff(models.Model):
    class Meta:
        verbose_name = u'The stuff'
        verbose_name_plural = u'The bunch of stuff'

You have verbose_name, however you want to customise app_label too for different display in admin. Unfortunatelly having some arbitrary string (with spaces) doesn’t work and it’s not for display anyway.

Turns out that the admin uses app_label. title () for display so we can make a little hack: str subclass with overriden title method:

class string_with_title(str):
    def __new__(cls, value, title):
        instance = str.__new__(cls, value)
        instance._title = title
        return instance

    def title(self):
        return self._title

    __copy__ = lambda self: self
    __deepcopy__ = lambda self, memodict: self

Now we can have the model like this:

class Stuff(models.Model):
    class Meta:
        app_label = string_with_title("stuffapp", "The stuff box")
        # 'stuffapp' is the name of the django app
        verbose_name = 'The stuff'
        verbose_name_plural = 'The bunch of stuff'

and the admin will show “The stuff box” as the app name.

“””


回答 9

如果您已经有使用旧应用程序名称的现有表,并且不想迁移它们,则只需在原始模型的代理上设置app_label。

class MyOldModel(models.Model):
    pass

class MyNewModel(MyOldModel):
    class Meta:
        proxy = True
        app_label = 'New APP name'
        verbose_name = MyOldModel._meta.verbose_name

然后,您只需要在admin.py中进行更改:

#admin.site.register(MyOldModel, MyOldModelAdmin)
admin.site.register(MyNewModel, MyOldModelAdmin)

请注意,URL为/ admin / NewAPPname / mynewmodel /,因此您可能只想确保新模型的类名看起来尽可能接近旧模型。

If you already have existing tables using the old app name, and you don’t want to migrate them, then just set the app_label on a proxy of the original model.

class MyOldModel(models.Model):
    pass

class MyNewModel(MyOldModel):
    class Meta:
        proxy = True
        app_label = 'New APP name'
        verbose_name = MyOldModel._meta.verbose_name

Then you just have to change this in your admin.py:

#admin.site.register(MyOldModel, MyOldModelAdmin)
admin.site.register(MyNewModel, MyOldModelAdmin)

Be aware that the url will be /admin/NewAPPname/mynewmodel/ so you might just want to make sure that the class name for the new model looks as close to the old model as possible.


回答 10

好吧,这对我有用。在app.py中使用以下命令:

class MainConfig(AppConfig):
    name = 'main'
    verbose_name="Fancy Title"

在setting.py中添加App的名称和App文件夹中app.py文件中存在的类名称

INSTALLED_APPS = [
    'main.apps.MainConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

]

Well, this works for me. In the app.py use this:

class MainConfig(AppConfig):
    name = 'main'
    verbose_name="Fancy Title"

In setting.py add the name of App and the class name present in app.py file in App folder

INSTALLED_APPS = [
    'main.apps.MainConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

]


回答 11

自以来,以下即插即用的代码完美地发挥了作用Django 1.7。您所要做的就是将以下代码复制__init__.py到特定应用程序的文件中并更改VERBOSE_APP_NAME参数。

from os import path
from django.apps import AppConfig

VERBOSE_APP_NAME = "YOUR VERBOSE APP NAME HERE"


def get_current_app_name(file):
    return path.dirname(file).replace('\\', '/').split('/')[-1]


class AppVerboseNameConfig(AppConfig):
    name = get_current_app_name(__file__)
    verbose_name = VERBOSE_APP_NAME


default_app_config = get_current_app_name(__file__) + '.__init__.AppVerboseNameConfig'

如果将其用于多个应用程序,则应将该get_current_app_name功能分解为帮助文件。

The following plug-and-play piece of code works perfectly since Django 1.7. All you have to do is copy the below code in the __init__.py file of the specific app and change the VERBOSE_APP_NAME parameter.

from os import path
from django.apps import AppConfig

VERBOSE_APP_NAME = "YOUR VERBOSE APP NAME HERE"


def get_current_app_name(file):
    return path.dirname(file).replace('\\', '/').split('/')[-1]


class AppVerboseNameConfig(AppConfig):
    name = get_current_app_name(__file__)
    verbose_name = VERBOSE_APP_NAME


default_app_config = get_current_app_name(__file__) + '.__init__.AppVerboseNameConfig'

If you use this for multiple apps, you should factor out the get_current_app_name function to a helper file.