Im trying to change a form from RadioSelect to MultipleChoice
with this form, I can see and the form in my tempalte as RadioButtons and can fill and save.
class TestForm(forms.Form):
def __init__(self, question, *args, **kwargs):
super(TestForm, self).__init__(*args, **kwargs)
choice_list = [x for x in question.get_answers_list()]
self.fields["answers"] = forms.ChoiceField(choices=choice_list,
widget=RadioSelect)
But, when I change to
widget=CheckboxSelectMultiple
Then I can see and select all Choices, but after saving the page is reloading without saving.
class TestTake(FormView):
form_class = TestForm
template_name = 'question.html'
result_template_name = 'result.html'
single_complete_template_name = 'single_complete.html'
def dispatch(self, request, *args, **kwargs):
self.quiz = get_object_or_404(Quiz, url=self.kwargs['quiz_name'])
if self.quiz.draft and not request.user.has_perm('quiz.change_quiz'):
raise PermissionDenied
if self.logged_in_user:
self.sitting = Sitting.objects.user_sitting(request.user,
self.quiz)
else:
self.sitting = self.anon_load_sitting()
if self.sitting is False:
return render(request, self.single_complete_template_name)
return super(TestTake, self).dispatch(request, *args, **kwargs)
How can I insert a Multiple Select checkbox here?
Related
I have a model which has a field 'keywords'. When I use a form to create/modify records, I am able to clean this field and then save it.
class ILProjectForm(forms.ModelForm):
class Meta:
models = ILProject
fields = '__all__'
def clean_keywords(self):
k = self.cleaned_data.get('keywords')
if k:
k = ','.join([a.strip() for a in re.sub('\\s+', ' ', k).strip().split(',')])
return k
However, I am not sure how to run clean() to update the data when I am using the list_editable option in the admin page.
I tried something like this bit I get an error saying I cannot set an attribute. What is the correct way to update the data after it has been cleaned?
class MyAdminFormSet(BaseModelFormSet):
def clean(self):
print(type(self.cleaned_data))
recs = []
for r in self.cleaned_data:
if r['keywords']:
r['keywords'] = ','.join([a.strip() for a in re.sub('\\s+', ' ', r['keywords']).strip().split(',')])
print(r['keywords'])
recs.append(r)
self.cleaned_data = recs <-- this part is problematic.
class ILProjectAdmin(...)
...
def get_changelist_formset(self, request, **kwargs):
kwargs['formset'] = MyAdminFormSet
return super().get_changelist_formset(request, **kwargs)
It should be like this:
class ILProjectAdmin(...)
...
def get_changelist_form(self, request, **kwargs):
return ILProjectForm
Please refer this tip: Django: Access request object from admin's form.clean()
class ProjectRequestForm(forms.ModelForm):
class Meta:
model = ProjectRequest
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(ProjectRequestForm, self).__init__(*args, **kwargs)
def clean(self):
if self.request.user.has_perm('access_role'):
raise ValidationError(f'No permission', code='invalid')
class ProjectRequestAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(ProjectRequestAdmin, self).get_form(request, obj, **kwargs)
class AdminFormWithRequest(form):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return form(*args, **kwargs)
return AdminFormWithRequest
def get_changelist_form(self, request, **kwargs):
class AdminFormWithRequest(ProjectRequestForm):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return ProjectRequestForm(*args, **kwargs)
return AdminFormWithRequest
I am building a CRM where I want each client to have multiple plans, and each plan to have multiple notes. When a user creates a new note, I want them to be able to select a relevant plan from a dropdown of plans belonging to the client. From what I can find, I should be able to get the contact_id from the kwargs, but my errors show nothing in kwargs. I know there should be a way to do this, but I can't seem to find it.
Variable Value
__class__ <class 'lynx.forms.SipNoteForm'>
args ()
kwargs {}
self <SipNoteForm bound=False, valid=Unknown, fields=(sip_plan;note;note_date;fiscal_year;quarter;class_hours;instructor;clients)>
Views.py
#login_required
def add_sip_note(request, contact_id):
form = SipNoteForm()
if request.method == 'POST':
form = SipNoteForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.contact_id = contact_id
form.user_id = request.user.id
form.save()
return HttpResponseRedirect(reverse('lynx:client', args=(contact_id,)))
return render(request, 'lynx/add_sip_note.html', {'form': form})
Forms.py
class SipNoteForm(forms.ModelForm):
class Meta:
model = SipNote
exclude = ('created', 'modified', 'user', 'contact')
def __init__(self, *args, **kwargs):
super(SipNoteForm, self).__init__(*args, **kwargs)
self.fields['sip_plan'].queryset = SipPlan.objects.filter(contact_id=kwargs.get("contact_id"))
Urls.py
path('add-sip-note/<int:contact_id>/', views.add_sip_note, name='add_sip_note'),
You are trying to get the kwargs in __init__(self, *args, **kwargs) as
def __init__(self, *args, **kwargs):
contact_id = kwargs.pop('contact_id')
super(SipNoteForm, self).__init__(*args, **kwargs)
self.fields['sip_plan'].queryset = SipPlan.objects.filter(contact_id=contact_id)
But you are not passing contact_id kwargs to the form while posting. you should pass kwargs to the form you are going to get in __init__(self, *args, **kwargs) such as
#login_required
def add_sip_note(request, contact_id):
form = SipNoteForm()
if request.method == 'POST':
form = SipNoteForm(request.POST, contact_id=contact_id)
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)
In my forms.py I raise an validation error when the user is already a member of the project. If i try to add a user who is already a member the validation error gets perfectly raised, but then I get redirected to the template and I have no context any more.
Any Best Practices in raising a form validation error? What am I doing wrong?
class AddUserForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.project = kwargs.pop('project')
self.user = kwargs.pop('user')
super(AddUserForm, self).__init__(*args, **kwargs)
self._user_cache = None
def clean_user(self):
"""
Check if the user is already a member of the project.
"""
user = self.cleaned_data['user']
if ProjectMember.objects.filter(project=self.project, user=user).exists():
raise forms.ValidationError(_("User is already a member of this project."))
# store user instance we queried for here to prevent additional lookups.
self._user_cache = user
return user
views.py without the ProjectUpdate view because it does not matter in this case. The views are a little bit complicated, because I have 2 forms in one template. If you know any better way to accomplish this, let me know.
class ProjectDetailView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
view = ProjectDisplay.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if 'update_form' in request.POST:
view = ProjectUpdate.as_view()
elif 'add_user_form' in request.POST:
view = ProjectAddUser.as_view()
return view(request, *args, **kwargs)
class ProjectDisplay(DetailView):
model = Project
def get_context_data(self, **kwargs):
context = super(ProjectDisplay, self).get_context_data(**kwargs)
context['update_form'] = ProjectUpdateForm(initial={
'name': self.object.name,
'description': self.object.description
})
context['add_user_form'] = AddUserForm(project=self.object, user=self.request.user)
context['project'] = self.object
context['is_member'] = self.object.user_is_member(self.request.user)
return context
class ProjectAddUser(CreateView):
model = ProjectMember
form_class = AddUserForm
template_name = 'projects/project_detail.html'
def get_success_url(self):
return reverse('project_detail', kwargs={'slug': self.get_object().slug})
def get_object(self, queryset=None):
return Project.objects.get(slug=self.kwargs['slug'])
def get_form_kwargs(self):
kwargs = super(ProjectAddUser, self).get_form_kwargs()
kwargs.update({'project': self.get_object()})
kwargs.update({'user': self.request.user})
return kwargs
I have a ModelForm in my application in which I want to modify init function to add some customisation.
When init is commented out then the form works and validates properly. When I override init and go to url where the form is rendered it automatically says that "Field xyz is required"
Whats the cause of that problem?
class CreateListView(FormMixin, ListView):
def get_context_data(self, **kwargs):
self.object_list = self.get_queryset()
data = super(ListView, self).get_context_data()
data['object_list'] = self.get_queryset()
data['form'] = self.get_form(self.form_class)
return data
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
form = form.save()
return HttpResponseRedirect(form.get_absolute_url())
return self.form_invalid(self.get_context_data())
class ActionGroupForm(forms.ModelForm):
class Meta:
model = ActionGroup
def __init__(self, *args, **kwargs):
super(ActionGroupForm, self).__init__(args, kwargs)
You are missing *, **:
super(ActionGroupForm, self).__init__(*args, **kwargs)