为相关型号管理员创建代理模型的类别模型 [英] A Category model which creates proxy models for related model admin

查看:90
本文介绍了为相关型号管理员创建代理模型的类别模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我试图创建一个模型来定义在管理站点管理相关模型的动态代理模型,我有点麻烦。我知道这句话很混乱,所以我只是分享我的代码。

So I'm having a bit of trouble with trying to create a model that will define dynamic proxy models that manage a related model in the admin site. I know that sentence was confusing, so I'll just share my code instead.

models.py

models.py

class Cateogry(models.Model):
    name = models.CharField(...)

class Tag(models.Model):
    name = models.CharField(...)
    category = models.ForeignKey(Cateogry)

我想要实现的是在管理员网站中,而不是为标签模型提供一个ModelAdmin,对于每个类别,我将为所有相关标签提供一个modeladmin。我已经使用此答案实现了这一点。说我有一个名为A的类别:

What I want to achieve is that in the admin site, instead of having one ModelAdmin for the Tag model, for each category I will have a modeladmin for all related tags. I have achieved this using this answer. Say I have a category named A:

def create_modeladmin(modeladmin, model, name = None):
    class  Meta:
        proxy = True
        app_label = model._meta.app_label

    attrs = {'__module__': '', 'Meta': Meta}

    newmodel = type(name, (model,), attrs)

    admin.site.register(newmodel, modeladmin)
    return modeladmin

class CatA(TagAdmin):
    def queryset(self, request):
        qs = super(CatA, self).queryset(request)
        return qs.filter(cateogry = Cateogry.objects.filter(name='A'))

create_modeladmin(CatA, name='CategoryAtags', model=Tag)

但这还不够好,因为显然我还需要手动子类化TagAdmin模型,然后运行create_modeladmin。我需要做的是循环遍历所有的Category对象,每一个都为Tagadmin(以类别命名)创建一个动态子类,然后从中创建一个动态代理模型,这就是我的头开始旋转的地方。

But this is not good enough, because obviously I still need to manually subclass the TagAdmin model and then run create_modeladmin. What I need to do, is loop over all Category objects, for each one create a dynamic subclass for Tagadmin (named after the category), then create a dynamic proxy model from that, and this is where my head starts spinning.

for cat in Category.objects.all():
    NewSubClass = #somehow create subclass of TagAdmin, the name should be '<cat.name>Admin' instead of NewSubClass 
    create_modeladmin(NewSubClass, name=cat.name, model=Tag)

任何指导或帮助将不胜感激

Any guidance or help would be much appreciated

推荐答案

动态模型管理员不工作以及管理员注册模式的方式。
我建议在CategoryAdmin中创建子视图。

Dynamic ModelAdmins don't work well together with the way admin registeres models. I suggest to create subviews in the CategoryAdmin.

from django.conf.urls import patterns, url
from django.contrib import admin
from django.contrib.admin.options import csrf_protect_m
from django.contrib.admin.util import unquote
from django.core.urlresolvers import reverse

from demo_project.demo.models import Category, Tag

class TagAdmin(admin.ModelAdmin):
    # as long as the CategoryTagAdmin class has no custom change_list template
    # there needs to be a default admin for Tags
    pass
admin.site.register(Tag, TagAdmin)

class CategoryTagAdmin(admin.ModelAdmin):
    """ A ModelAdmin invoked by a CategoryAdmin"""

    read_only_fields = ('category',)

    def __init__(self, model, admin_site, category_admin, category_id):
        self.model = model
        self.admin_site = admin_site
        self.category_admin = category_admin
        self.category_id = category_id
        super(CategoryTagAdmin, self).__init__(model, admin_site)

    def queryset(self, request):
        return super(CategoryTagAdmin, self).queryset(request).filter(category=self.category_id)


class CategoryAdmin(admin.ModelAdmin):

    list_display = ('name', 'tag_changelist_link')

    def tag_changelist_link(self, obj):
        info = self.model._meta.app_label, self.model._meta.module_name
        return '<a href="%s" >Tags</a>' % reverse('admin:%s_%s_taglist' % info, args=(obj.id,))
    tag_changelist_link.allow_tags = True
    tag_changelist_link.short_description = 'Tags'

    @csrf_protect_m
    def tag_changelist(self, request, *args, **kwargs):
        obj_id = unquote(args[0])
        info = self.model._meta.app_label, self.model._meta.module_name

        category = self.get_object(request, obj_id)

        tag_admin = CategoryTagAdmin(Tag, self.admin_site, self, category_id=obj_id )

        extra_context = {
            'parent': {
                'has_change_permission': self.has_change_permission(request, obj_id),
                'opts': self.model._meta,
                'object': category,
            },
        }
        return tag_admin.changelist_view(request, extra_context)


    def get_urls(self):
        info = self.model._meta.app_label, self.model._meta.module_name
        urls= patterns('', 
            url(r'^(.+)/tags/$', self.admin_site.admin_view(self.tag_changelist), name='%s_%s_taglist' % info )
        )
        return urls + super(CategoryAdmin, self).get_urls()


admin.site.register(Category, CategoryAdmin)

类别更改列表中的项目具有一个带有链接的额外列de指向 CategoryAdmin.tag_changelist tag_changelist_link 。此方法创建一个具有某些附加功能的CategoryTagAdmin实例,并返回其changelist_view。

The items in the categories changelist have an extra column with a link made by the tag_changelist_link pointing to the CategoryAdmin.tag_changelist. This method creates a CategoryTagAdmin instance with some extras and returns its changelist_view.

这样,您可以在每个类别上对过滤的标签更改列表。要修复tag_changelist视图的导航痕迹,您需要将CategoryTagAdmin.change_list_template设置为自己的模板,该模板 {%extends'admin / change_list.html'%} 并覆盖 {%block breadcrumbs%} 。那就是你需要来自extra_context的 parent 变量来创建正确的URL。

This way you have a filtered tag changelist on every category. To fix the breadcrumbs of the tag_changelist view you need to set the CategoryTagAdmin.change_list_template to a own template that {% extends 'admin/change_list.html' %} and overwrites the {% block breadcrumbs %}. That is where you will need the parent variable from the extra_context to create the correct urls.

如果你打算实现 tag_changeview tag_addview 方法,您需要确保在variouse管理模板中呈现的链接指向正确的URL (例如,以form_url作为参数调用change_view)。
CategoryTagAdmin上的save_model方法可以在添加新标签时设置默认类别。

If you plan to implement a tag_changeview and tag_addview method you need to make sure that the links rendered in variouse admin templates point to the right url (e.g. calling the change_view with a form_url as paramter). A save_model method on the CategoryTagAdmin can set the default category when adding new tags.

def save_model(self, request, obj, form, change):
    obj.category_id = self.category_id
    super(CategoryTagAdmin, self).__init__(request, obj, form, change)

如果你还想坚持apache重新启动aproach ...是的,你可以重新启动Django。这取决于您如何部署实例。
在apache上,您可以触摸将重新加载实例的$ wsgi文件。 os.utime(path / to / wsgi.py
使用uwsgi您可以使用 uwsgi.reload()

If you still want to stick to the apache restart aproach ... Yes you can restart Django. It depends on how you are deploying the instance. On an apache you can touch the wsgi file that will reload the instance os.utime(path/to/wsgi.py. When using uwsgi you can use uwsgi.reload().

您可以检查 Rosetta 如何在保存翻译(views.py)后重新启动实例。

You can check the source code of Rosetta how they are restarting the instance after the save translations (views.py).

这篇关于为相关型号管理员创建代理模型的类别模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆