【问题标题】:How do I get the actual object id in a Django admin page (inside formfield_for_foreignkey)?如何在 Django 管理页面(在 formfield_for_foreignkey 内)中获取实际的对象 ID?
【发布时间】:2011-06-04 19:44:01
【问题描述】:

我已经解决了使用此代码获取正在编辑的对象 id 的问题:

class CompanyUserInline(admin.StackedInline):
    """
    Defines tabular rules for editing company users direct in company admin
    """
    model = CompanyUser

    def formfield_for_foreignkey(self, db_field, request, **kwargs):

        if db_field.name == "user":
            users = User.objects.filter( Q(is_superuser=False) )
            query = Q()
            for u in users:
                aux = CompanyUser.objects.filter(user=u)
                if aux.count() == 0:
                    query |= Q(pk=u.id)

            try:
                cpu = CompanyUser.objects.filter(company__id=int(request.path.split('/')[4]))
                for p in cpu:
                    query |= Q(pk=p.user.id)
            except:
                pass

            kwargs["queryset"] = User.objects.filter(query).order_by('username')

        return super(CompanyUserInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

但是,int(request.path.split('/')[4]) 真的很丑。我想知道如何从 Django AdminModel 获取 id。我确定它在里面的某个地方,有人知道吗?

提前感谢您! ;D

【问题讨论】:

标签: django django-models django-admin


【解决方案1】:

据我所知,无法通过formfield_for_...-方法访问当前实例,因为它们只会被单个字段实例调用!

更好的方法是使用get_form 来访问可以访问整个实例/表单的逻辑。您还可以在那里覆盖表单字段的查询集!

【讨论】:

  • 我在哪里可以找到一些关于 get_form 的文档?我试图通过它获取对象并且它有效,但我不知道如何使用该方法覆盖表单字段的查询集...... =/
  • 查看原代码code.djangoproject.com/browser/django/trunk/django/contrib/…。如果form 是原始get_form 方法返回的形式,form.base_fields 应该是字段对象的字典!
  • 好的!谢谢你,兄弟!我会看看它并在这里发布解决方案。如果我实现它!再次感谢你! ;D
【解决方案2】:

我正在处理类似的情况,并意识到我需要从请求中获得的 id,因为它是该模型的外键,所以我可以来自模型本身。所以它会是这样的:

cpu = CompanyUser.objects.filter(company__id=self.company_id)

或者你的模型结构所要求的。

【讨论】:

  • 您能否在此答案中添加更多上下文和解释。这条线是用什么方法进去的?什么级别?哪个模块?
【解决方案3】:

经过一番挖掘,我们能够获取传递给管理视图的参数(在被 django 管理员的 urls.py 解析之后)并使用该 (self_pub_id) 来获取对象:

class PublicationAdmin(admin.ModelAdmin):

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "authors":
            #this line below got the proper primary key for our object of interest
            self_pub_id = request.resolver_match.args[0]

            #then we did some stuff you don't care about
            pub = Publication.objects.get(id=self_pub_id)
            kwargs["queryset"] = pub.authors.all()
        return super(PublicationAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

更优雅的解决方案是使用接受的答案推荐并利用 get_form ModelAdmin 成员函数。像这样:

class ProfileAdmin(admin.ModelAdmin):
    my_id_for_formfield = None
    def get_form(self, request, obj=None, **kwargs):
        if obj:
            self.my_id_for_formfield = obj.id
        return super(ProfileAdmin, self).get_form(request, obj, **kwargs)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "person":
            kwargs["queryset"] = Person.objects.filter(profile=self.my_id_for_formfield)
        return super(ProfileAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

【讨论】:

  • 嘿自我,这太老套了!!但它有效。我们又遇到了自己的路。
  • 可以事件存储整个对象,不需要只存储id。不过很好的解决方案!
  • 非常感谢,你为我节省了一些时间,实际上对我来说,django 2.2.5 是在 request.resolver_match.kwargs.get('object_id', None)
【解决方案4】:

我通过在 model.py 中创建一个返回 ID 的 property() 使其工作

models.py:

class MyModel(models.Model):
    myfield = models.CharField(max_length=75)
    ...
    def get_id(self):
        return str(self.id)
    getid = property(get_id)

admin.py:

from myapp.models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    list_display = ['mylink',]
    def mylink(self, object):
        return '<a href="http://mywebsite/'+object.getid+'/">Edit</a>'
    mylink.allow_tags = True

admin.site.register(MyModel, MyModelAdmin)

【讨论】:

  • 这很简单。我想要一种在 formfield_for_foreignkey 中使用 id 的方法,而不是简单地向用户显示。
  • 同意,这不能回答问题。
【解决方案5】:

我通过重写change_view()使其工作

class CartAdmin(admin.ModelAdmin):

def change_view(self, request, object_id, form_url='', extra_context=None):
    self.object_id = object_id
    return self.changeform_view(request, object_id, form_url, extra_context)


def formfield_for_foreignkey(self, db_field, request, **kwargs):
    print self.object_id
    return super(CartAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

那么你可以在formfield_for_foreignkey()里面调用self.object_id

【讨论】:

  • 对我来说效果很好,但是如果在进行修改后值仍然很高,要重置它,您必须在 add_view 中执行相同操作并设置 self.object_id = None 的值
【解决方案6】:

以下代码 sn -p 将为您提供对象 id:

request.resolver_match.kwargs['object_id']

示例用法:(我正在过滤显示的电话号码,只显示客户的电话号码)

def formfield_for_foreignkey(self, db_field, request, **kwargs):
    if db_field.name == 'preferred_contact_number':
        kwargs['queryset'] = CustomerPhone.objects.filter(customer__pk=request.resolver_match.kwargs['object_id'])
    return super().formfield_for_foreignkey(db_field, request, **kwargs)

P.S:通过调试和遍历可访问变量找到它。

【讨论】:

  • 这是最好的方法!
【解决方案7】:

更通用的方法是编写一个辅助方法来获取模型实例(如果有),就像您通常使用(有界)ModelForm 所做的那样,并从中检索 id 或任何其他属性:

from django.contrib import admin

class MyModelAdmin(admin.ModelAdmin):

    def get_instance(self, request):
        try:
            object_id = request.resolver_match.kwargs['object_id']
            obj = self.get_object(request, object_id)
        except:
            obj = None
        return obj

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-15
    • 2013-04-26
    • 2018-04-18
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 2013-11-07
    • 2012-06-24
    相关资源
    最近更新 更多