Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the actual object id in a Django admin page (inside formfield_for_foreignkey)?

I 've already solved the problem of getting the object id being edited using this code:

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)

But, the int(request.path.split('/')[4]) is really ugly. I want to know how I get the id from the Django AdminModel. I'm sure it's somewhere inside it, anyone knows?

Thank you in advance! ;D

like image 255
Jayme Tosi Neto Avatar asked Jan 06 '11 18:01

Jayme Tosi Neto


People also ask

How do I find my Django ID?

One way to show the ID field is to make it editable by removing editable=False from the model definition.

What we can do in admin portal in Django?

Overview. The Django admin application can use your models to automatically build a site area that you can use to create, view, update, and delete records. This can save you a lot of time during development, making it very easy to test your models and get a feel for whether you have the right data.


2 Answers

After some digging around, we were able to grab the arguments that get passed to the admin view (after being parsed by django admin's urls.py) and use that (self_pub_id) to grab the object:

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)

A more elegant solution is to use the accepted answers recomendation and leverage the get_form ModelAdmin member function. Like so:

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)
like image 166
FizxMike Avatar answered Sep 18 '22 08:09

FizxMike


The following code snippet will give you the object id:

request.resolver_match.kwargs['object_id']

Sample usage: (I'm filtering the phone numbers shown, to only show customer's phone numbers)

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: Found it by debugging and walking through accessible variables.

like image 24
Maziyar Mk Avatar answered Sep 19 '22 08:09

Maziyar Mk