2

I want for filter a ModelChoiceField with the current user. I found a solution very close that I want to do, but I dont understand Django: How to get current user in admin forms

The answer accepted says

"I can now access the current user in my forms.ModelForm by accessing self.current_user"

--admin.py

class Customer(BaseAdmin):
form = CustomerForm

def get_form(self, request,obj=None,**kwargs):
    form = super(Customer, self).get_form(request, **kwargs)
    form.current_user = request.user
    return form

--forms.py

class CustomerForm(forms.ModelForm):

default_tax =   forms.ModelChoiceField(queryset=fa_tax_rates.objects.filter(tenant=????)) 
class Meta:
    model   = fa_customers

How do I get the current user on modelchoice queryset(tenant=????) How do I call the self.current_user in the modelform(forms.py)

Community
  • 1
  • 1
NeDiaz
  • 349
  • 3
  • 14

2 Answers2

1

Override __init__ constructor of the CustomerForm:

class CustomerForm(forms.ModelForm):
    ...
    def __init__(self, *args, **kwargs):
        super(CustomerForm, self).__init__(*args, **kwargs)
        self.fields['default_tax'].queryset = 
                        fa_tax_rates.objects.filter(tenant=self.current_user))

Queryset in the form field definition can be safely set to all() or none():

class CustomerForm(forms.ModelForm):
    default_tax = forms.ModelChoiceField(queryset=fa_tax_rates.objects.none()) 
catavaran
  • 44,703
  • 8
  • 98
  • 85
  • 1
    it raises an error: Exception Value: type object 'fa_customersForm' has no attribute 'fields' Exception Location: /Users/nelsondiaz/Sites/myinvo/myinvoapp/admin.py in get_form, line 44 – NeDiaz Jan 20 '15 at 06:18
  • Sorry, my bad. `ModelAdmin.get_form()` returns not the form instance but a form class. You can access that class property from the `__init__` constructor. See the corrected answer. – catavaran Jan 20 '15 at 06:43
  • So frustrated, something that should be simple it's not. code Exception Type: AttributeError Exception Value: 'fa_customersForm' object has no attribute 'current_user' code Where should be the init? ModelForm or ModelAdmin? I have saw examples with view isnt it posible create without a view? I'm using the default admin – NeDiaz Jan 20 '15 at 16:19
  • `__init__` should be in the `CustomerForm`. And `current_user` attribute is set in the `Customer.get_form()` method. – catavaran Jan 21 '15 at 01:57
  • 1
    Thanks A lot. Urrrra!!!!!! I'm going to detail that I do, I felt confused because in some examples show get_form and another init but not both – NeDiaz Jan 21 '15 at 15:47
  • 1.- Define the model --model.pyclass fa_customers(models.Model): tenant = models.ForeignKey(User,null=True,blank=True) name = models.CharField(max_length=100) default_tax = models.ForeignKey(fa_tax_rates,null=True,blank=True) ... class fa_tax_rates(models.Model): tenant = models.ForeignKey(User,null=True,blank=True) tax_code = models.CharField(max_length=25) rate = models.DecimalField(max_digits=5, decimal_places=2, validators=[MinValueValidator(0.01)]) – NeDiaz Jan 21 '15 at 16:02
  • 2.- Add the model in your admin, passing the user using get_form -- admin.py class Customer(BaseAdmin): form = CustomerForm def get_form(self, request, obj=None, **kwargs): form = super(Customer, self).get_form(request, obj, **kwargs) form.current_user = request.user return form – NeDiaz Jan 21 '15 at 16:02
  • 3.- Define your for in forms.py getting the current user through __init__ passed by get_form in admin.py --forms.py class CustomerForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(CustomerForm, self).__init__(*args, **kwargs) self.fields['default_tax'].queryset = fa_tax_rates.objects.filter(tenant=self.current_user) class Meta: model = fa_customers – NeDiaz Jan 21 '15 at 16:02
1

Just to sum up the solution because it was very hard for me to make this work and understand the accepted answer

In admin.py

class MyModelForm (forms.ModelForm):

    def __init__(self, *args,**kwargs):
    super (MyModelForm ,self).__init__(*args,**kwargs)
    #retrieve current_user from MyModelAdmin
    self.fields['my_model_field'].queryset = Staff.objects.all().filter(person_name = self.current_user)

#The person name in the database must be the same as in Django User, otherwise use something like person_name__contains

class MyModelAdmin(admin.ModelAdmin):
    form = MyModelForm 

    def get_form(self, request, *args, **kwargs):
        form = super(MyModelAdmin, self).get_form(request, *args, **kwargs)
        form.current_user = request.user #get current user only accessible in MyModelAdminand pass it to MyModelForm
        return form
VMMF
  • 906
  • 1
  • 17
  • 28