0

I'm trying to change the default value of a foreignkey-formfield to set a Value of an other model depending on the logged in user. But I'm racking my brain on it...

This: Changing ForeignKey’s defaults in admin site would an option to change the empty_label, but I need the default_value.

#Now I tried the following without errors but it didn't had the desired effect:
class EmployeeAdmin(admin.ModelAdmin):
...
  def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
    formfields= super(EmployeeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
    
    if request.user.is_superuser:
        return formfields
    if db_field.name == "company":
        #This is the RELEVANT LINE
        kwargs["initial"]  = request.user.default_company
        
    return db_field.formfield(**kwargs)

    
admin.site.register(Employee, EmployeeAdmin)

##################################################################
# REMAINING Setups if someone would like to know it but i think
# irrelevant concerning the problem
##################################################################
from django.contrib.auth.models import User, UserManager
class CompanyUser(User):
    ...
    objects = UserManager()
    company = models.ManyToManyField(Company)
    default_company= models.ForeignKey(Company, related_name='default_company')
    #I registered the CompanyUser instead of the standard User, 
    #   thats all up and working
    ...

class Employee(models.Model):
    company = models.ForeignKey(Company)
    ...

Hint: kwargs["default"] ... doesn't exist.

Thanks in advance, Nick

Community
  • 1
  • 1
Nick Ma.
  • 21
  • 1
  • 6

2 Answers2

2

I think the db_field.formfield method (which is also called by the admin btw) always overwrites your inital value with the default value specified in the model! So you need to specify the right form field yourself:

from django import forms

class EmployeeAdmin(admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, **kwargs):
        user = kwargs['request'].user
        if db_field.name == "company":
            kwargs['initial'] = user.default_company
            qs = Company.objects.all()
            return forms.ModelChoiceField(queryset=qs, **kwargs)
        return super(EmployeeAdmin, self).formfield_for_dbfield(db_field, **kwargs)

You could also do this customization in a custom form's init, but the problem is, that you cannot access request normally in a form class, but you can see my hack here Django: How to get current user in admin forms on how to get the current user object into the form!

Community
  • 1
  • 1
Bernhard Vallant
  • 49,468
  • 20
  • 120
  • 148
  • First: Thanks! second: I gave it a try with formfield_for_dbfield but: With: ---- user = kwargs.get("request", None) i got a -> "global name 'request' is not defined" ---- and with: field = super(EmployeeAdmin, self).formfield_for_dbfield(db_field, **kwargs) field.user = kwargs.get('request', None).user i got -> 'NoneType' object has no attribute 'user' – Nick Ma. Jun 02 '10 at 19:07
  • I'm not sure if formfield_for_dbfield overwrites it, because formfield_for_foreignkey will be call from it (http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py - line 101) – Nick Ma. Jun 02 '10 at 19:12
  • You're right, but I meant it is overwritten in the FIELD's formfield method, which is called after (from the admin's method line 155)! – Bernhard Vallant Jun 03 '10 at 09:39
  • ok thanks alot, the code do compiles now but I still don't get the right effect :-/ Is kwargs['initial'] the right thing? – Nick Ma. Jun 03 '10 at 17:38
  • The only thing at your code is that every Time I implement the line I get an <__init__() got an unexpected keyword argument 'request'> @ /usr/lib/python2.6/dist-packages/django/forms/models.py in __init__, line 937 – Nick Ma. Jun 03 '10 at 17:47
  • ah, damnit I think i got it.. gimme 10mins. :) – Nick Ma. Jun 03 '10 at 18:16
  • I think you have it all working now... But otherwise I guess it should have been user = kwargs.pop('request').user, if the method doesnt want to have request in there.... – Bernhard Vallant Jun 04 '10 at 13:21
0

ok, the kwargs['initial'] thing worked the whole time but it just give a damn if you give it an object (like I did with: kwargs['initial'] = user.default_company). But it's working with an Integer.

I solved it like this:

def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
    formfields= super(EmployeeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

    if request.user.is_superuser:
        return formfields

    if db_field.name == "company":
        qs= request.user.company.all()
        #determine the default pos of configured default_company
        for index, item in enumerate(qs):
            if item==request.user.default_company:
                kwargs["initial"]  = index+1
                break
        #restrict shown entries in the ModelChoiceField
        kwargs["queryset"] = qs


    return db_field.formfield(**kwargs)

Sorry for the stress and thanks for helping!

Nick Ma.
  • 21
  • 1
  • 6