Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I give `def formfield_for_manytomany` an id of editable object

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)

How can I give def formfield_for_manytomany an id of editable object?

like image 621
maksymov Avatar asked Mar 06 '11 21:03

maksymov


2 Answers

Assuming you're after the Report instance being edited by the ReportAdmin, try this:

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)
like image 54
DrMeers Avatar answered Nov 15 '22 05:11

DrMeers


The problem with DrMeer's otherwise excellent answer is that the object will be cached inside the ModelAdmin instance and its lifetime will extend until next get_object() call. However, get_object() is not called when adding a new report, so the wrong, previous report obj will be present when you add a new report after changing an existing report.

A safer approach is to cache the report object in the request, so it has request scope:

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)
like image 29
mrts Avatar answered Nov 15 '22 06:11

mrts