【问题标题】:How can I give `def formfield_for_manytomany` an id of editable object我怎样才能给`def formfield_for_manytomany`一个可编辑对象的ID
【发布时间】:2011-07-09 23:23:49
【问题描述】:
class Report(models.Model):
    precursor = models.ManyToManyField(Precursor)

class ReportAdmin(admin.ModelAdmin):
    def formfield_for_manytomany(self, db_field, request, **kwargs):
        ops_area = Report.objects.get(id=???????).ops_area
        print id
        print ops_area
        if db_field.name == "r_precursor":
            kwargs["queryset"] = Precursor.objects.filter(ops_area=ops_area)
            print kwargs
        return super(ReportAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

如何给def formfield_for_manytomany 一个可编辑对象的ID?

【问题讨论】:

    标签: django django-models django-admin django-forms


    【解决方案1】:

    DrMeer 的出色答案的问题在于该对象将被缓存在 ModelAdmin 实例中,并且其生命周期将延长到下一次 get_object() 调用。但是,在添加新报告时不会调用get_object(),因此在更改现有报告后添加新报告时,会出现错误的先前报告obj

    更安全的方法是将报表对象缓存在request中,因此它具有请求范围:

    class ReportAdmin(admin.ModelAdmin):
        def get_object(self, request, object_id, from_field=None):
            obj = super().get_object(request, object_id, from_field=from_field)
            # Cache object for use in formfield_for_manytomany
            request.report_obj = obj
            return obj
    
        def formfield_for_manytomany(self, db_field, request, **kwargs):
            if db_field.name == "r_precursor" and hasattr(request, 'report_obj'):
                kwargs["queryset"] = Precursor.objects.filter(
                    ops_area=request.report_obj.ops_area)
            return super(ReportAdmin, self).formfield_for_manytomany(
                db_field, request, **kwargs)
    

    【讨论】:

      【解决方案2】:

      假设您在 Report 正在编辑的 ReportAdmin 实例之后,试试这个:

      class ReportAdmin(admin.ModelAdmin):
          def get_object(self, request, object_id):
              # Hook obj for use in formfield_for_manytomany
              self.obj = super(ReportAdmin, self).get_object(request, object_id)
              print "Got object:", self.obj
              return self.obj
      
          def formfield_for_manytomany(self, db_field, request, **kwargs):
              if db_field.name == "r_precursor" and getattr(self, 'obj', None):
                  kwargs["queryset"] = Precursor.objects.filter(
                      ops_area=self.obj.ops_area)
              return super(ReportAdmin, self).formfield_for_manytomany(
                  db_field, request, **kwargs)
      

      【讨论】:

      • 'ReportAdmin' 对象没有属性 'obj'
      • 抱歉,这个钩子只能在 Inline 中工作——试试更新的代码(注意我还在第二种方法中添加了getattr
      • 这对我来说根本不起作用。 get_object 永远不会被调用。据我所知,模型管理员的方法也没有记录。
      • 这取决于你在哪里使用它(也可能是 Django 的版本)。您也可以在get_formget_formset 方法中尝试。请参阅我的 pre-edited post 了解适用于内联的版本。
      • DrMeers 你的定义是THE MAN。让它与您的预编辑和使用 get_form 的组合一起工作。这是一场多么艰难的斗争。感谢您的帮助!
      猜你喜欢
      • 1970-01-01
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      相关资源
      最近更新 更多