The below code removes certain values from a drop down menu.
It works fine but I want to remove the value if the user lacks certain permissions.
How can I access request.user in the ModelForm's constructor? Or is there a better way to accomplish what I am trying to do?
class AnnouncementModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(AnnouncementModelForm, self).__init__(*args, **kwargs)
self.fields["category"].queryset = AnnouncementCategory.objects.filter(can_post=True)
How can I access request.user in the ModelForm's constructor?
To use it in the Form constructor, just pass the request to it.
class AnnouncementModelForm(forms.ModelForm):
def __init__(self, request, *args, **kwargs):
super(AnnouncementModelForm, self).__init__(*args, **kwargs)
qs = request.user.foreignkeytable__set.all()
self.fields["category"].queryset = qs
Ok here is how I solved it:
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "category" and not request.user.has_perm('can_post_to_all'):
kwargs["queryset"] = AnnouncementCategory.objects.filter(can_post=True)
return db_field.formfield(**kwargs)
return super(AnnouncementAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Related
Is it even possible?
I can't find anything or figure it out by myself since I'm a beginner, so I turn to you guys.
Here's an example (don't worry about the use case, I just want to know if it's possible and how):
When I run this code I get that *args is not defined. What's wrong?
views.py:
class MyCreateView(CreateView):
def get(self, request, *args, **kwargs):
slug = kwargs['slug']
helper_method(self, slug)
helpers.py:
def helper_method(self, slug):
if slug == "random":
return super(self.__class__, self).get(request, *args, **kwargs)
You have to define args and kwargs, you just need to add them to your method parameters like this:
def helper_method(self, slug, *args, **kwargs):
if slug == "random":
return super(self.__class__, self).get(request, *args, **kwargs)
class MyCreateView(CreateView):
def get(self, request, *args, **kwargs):
slug = kwargs['slug']
helper_method(self, slug, *args, **kwargs)
hi im trying to use the above forms - but i get
__init__() takes at least 2 arguments (1 given)
i get to the form that it should show but it never save me the new password
i also needed to change the:
def __init__(self, user, *args, **kwargs):
self.user = user
super(AdminPasswordChangeForm, self).__init__(*args, **kwargs)
to:
def __init__(self, *args, **kwargs):
super(AdminPasswordChangeForm, self).__init__(*args, **kwargs)
since it doesnt get a user arg.
any ideas why?
thx
============================ edit =============================================
class set(FormView):
model = User
form_class = AdminPasswordChangeForm
template_name = 'set.html'
def dispatch(self, request, *args, **kwargs):
return super(set, self).dispatch(request, *args, **kwargs)
def get_form_kwargs(self):
kwargs = super(set, self).get_form_kwargs()
kwargs['user_to_update'] = the user
return kwargs
the init:
def __init__(self, *args, **kwargs):
self.user = kwargs['user_to_update']
kwargs.pop('user_to_update')
super(AdminPasswordChangeForm, self).__init__(*args, **kwargs)
Use the existing form. Overide the view's get_form_kwargs method to pass the expected arguments to the form, instead of changing the __init__ method, which will break other things.
In order to save the password, you need to override the form_valid method and call form.save().
For create and update views, you don't always need to override form_valid, because the default behaviour is to save the form and redirect. For FormView, the default behaviour is simply to redirect, so you do have to override it to get it to do anything useful.
class SetPasswordView(FormView):
form_class = AdminPasswordChangeForm
template_name = 'set.html'
success_url = '/thanks/'
def get_form_kwargs(self):
kwargs = super(set, self).get_form_kwargs()
kwargs['user_to_update'] = the user
return kwargs
def form_valid(self, form):
form.save()
return super(SetPasswordView, self).form_valid(form)
I have a django form name "SampleForm". Which i use to take input from user. Now i want to use same form to show this information to user on a different page. But form is editable I want to make the form read only. Is there any way to make whole form Readonly ?
pseudo-code (not tested):
class ReadOnlyFormMixin(ModelForm):
def __init__(self, *args, **kwargs):
super(ReadOnlyFormMixin, self).__init__(*args, **kwargs)
for key in self.fields.keys():
self.fields[key].widget.attrs['readonly'] = True
def save(self, *args, **kwargs):
# do not do anything
pass
class SampleReadOnlyForm(ReadOnlyFormMixin, SampleForm):
pass
class SampleForm(ModelForm):
def __init__(self, *args, **kwargs):
super(SampleForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
if instance and instance.pk:
for field in self.fields.keys():
self.fields[field].widget.attrs['readonly'] = True
Just this should make the entire form readonly whenever an instance is available for the form.
Working Code
class ReadOnlySampleForm(SampleForm):
def __init__(self, *args, **kwargs):
super(SampleForm, self).__init__(*args, **kwargs)
for key in self.fields.keys():
self.fields[key].widget.attrs['readonly'] = True
in Django 4.1, override the get_context_data with
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=None, **kwargs)
form = AddressForm(instance=self.get_object())
for name, field in form.fields.items():
field.disabled = True
context["form"] = form
return context
I have a simple form which uses a queryset that is set dynamically:
class FooForm(forms.Form):
bar = forms.ModelChoiceField(queryset = Bar.objects.none())
def __init__(self, queryset=None, *args, **kwargs):
super(FooForm, self).__init__(*args, **kwargs)
self.fields['bar'].queryset = queryset
I'd like to use this as one of my forms in a FormWizard, but I can't figure out how I can get FormWizard to pass on the queryset. Is this possible at all?
I think you could override the "get_form" method for that particular wizard
class MyWizard(FormWizard):
def __init__(self, *args, **kwargs):
self.querysets = kwargs.pop('querysets', None)
super(self, MyWizard).__init__(*args, **kwargs)
def get_form(self, step, data=None, *args, **kwargs):
return self.form_list[step](data, prefix=self.prefix_for_step(step), initial=self.initial.get(step, None), queryset=self.querysets.get(step, None))
def done(self, *args, **kwargs): pass
I'm trying to use validation with the request.user object to restrict updates to some rows for specific users within the django admin site. I get the impression I need to override the ModelAdmin change_view method to pass the request object to the form. I've looked at the change_view method in django.contrib.admin.options, but as someone very new to django, am having trouble understanding where in the change_view method I need to make these modifications. Any pointers in the right direction would be great.
class IssuesAdmin(admin.ModelAdmin):
def change_view(self, request, object_id, extra_context=None):
#modify lines to pass request to form
form = IssuesAdminForm
class IssuesAdminForm(forms.ModelForm):
class Meta:
model = Issues
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(IssuesAdminForm, self).__init__(*args, **kwargs)
def clean_product(self):
if self.request.user.name=='someone'
return self.cleaned_data["product"]
else:
raise forms.ValidationError("Nope!")
class IssuesAdmin(admin.ModelAdmin):
def change_view(self, request, object_id, extra_context=None): #remember to edit also add_view()... etc
self.form.request = request
form = IssuesAdminForm
class IssuesAdminForm(forms.ModelForm):
class Meta:
model = Issues
def __init__(self, *args, **kwargs):
self.request = # do what you need ;)
super(IssuesAdminForm, self).__init__(*args, **kwargs)
def clean_product(self):
if self.request.user.name=='someone'
return self.cleaned_data["product"]
else:
raise forms.ValidationError("Nope!")