i have model, admin and form for it. But there is a field in my form that is not in the model and i'm doing some custom action with that field.
I want this field to be readonly or hidden or disabled for users without some permissions, but django doesn't allow me to dynamically set any of these attributes.
My model:
class PromocodePool(TimeStampedModel):
start = models.DateTimeField()
end = models.DateTimeField(null=True, blank=True)
Form:
class PromocodePoolForm(forms.ModelForm):
promocodes = forms.FileField(widget=AdminFileWidget, required=False) # this field is non-model
class Meta:
model = PromocodePool
fields = '__all__'
Admin:
@admin.register(PromocodePool)
class PromocodePoolAdmin(admin.ModelAdmin):
form = PromocodePoolForm
list_display = ("get_start", "get_end")
readonly_fields = (<some fields, tuple>)
@admin.display(description="Start date")
def get_start(self, obj):
return _date(obj.start, formats.DATE_FORMAT)
@admin.display(description="Start date")
def get_end(self, obj):
return _date(obj.end, formats.DATE_FORMAT)
def get_readonly_fields(self, request, obj=None):
if not request.user.has_perm("promocode.custom_permission"):
self.readonly_fields = ("promocodes",) # this doesn't work
return self.readonly_fields
Im getting this error:
Unable to lookup 'promocodes' on PromocodePool or PromocodePoolAdmin or PromocodePoolForm
Btw if i rename my form, error text stays the same because the real "finish" form generates via django's ModelFormMetaclass and is called PromocodePoolForm and this form is not my form described above.
Is there any way to dynamically disable this field?
If it's matters, im using python 3.8 and Django 3.2.6
Thanks comment below i googled further and solved my problem.
I made two form classes instead of one i had before
class PromocodePoolForm(forms.ModelForm):
promocodes = forms.FileField(widget=AdminFileWidget, required=False, disabled=True)
# no validation/processing for this non-model field in this class
# just disabled field
class Meta:
model = PromocodePool
fields = '__all__'
class PromocodePoolFormNotDisabled(PromocodePoolForm):
promocodes = forms.FileField(widget=AdminFileWidget, required=False)
# all validation/processing for non-model field is in this class now
And added this method to admin class instead of get_readonly_fields
@admin.register(PromocodePool)
class PromocodePoolAdmin(admin.ModelAdmin):
form = PromocodePoolForm
...
def get_form(self, request, obj=None, change=False, **kwargs):
if request.user.has_perm("promocode.custom_permission"):
self.form = PromocodePoolFormNotDisabled
return super().get_form(request, obj, change, **kwargs)
And it worked like a charm: if user doesn't have permission, he gets form with disabled field otherwise he gets normal one.
CodePudding user response:
It seems, that you can override the get_forms method, checking user custom permissions there, and returning your custom form. I don't know, for shure, that it's a good way to do this, but in my case it worked)