I’ve made good progress today with forms but I’ve become stuck with how to update a users manytomany field. I am using the get_success_url method to try and write the created object id to the user model manytomany field event_access but I’m baffled how to do this. A pointer in the right direction would be appreciated.
class EventCreate(CreateView):
def get_form(self, form_class=None):
form = super(EventCreate, self).get_form(form_class)
form.fields['association'].queryset = self.request.user.asc_access
form.fields['association'].initial = self.kwargs["association_id"]
form.fields['when'].widget = AdminDateWidget(attrs={'type': 'date'})
form.fields['time'].widget = AdminDateWidget(attrs={'type': 'time'})
return form
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
def form_valid(self, form):
self.request.user
if form.cleaned_data['when'] < timezone.localdate():
form.add_error('when', 'Date is in the past')
return self.form_invalid(form)
return super().form_valid(form)
def get_success_url(self):
# Update user's list of allowed events to edit
self.request.user.event_access.value = self.object.id
print(self.object.id)
breakpoint()
return reverse("showorderofplay:events", args=[self.kwargs["association_id"]])
model = Event
fields = ['name', 'when', 'time', 'description',
'active', 'cancelled', 'association']
initial = {}
First, you’d be better off doing this work in form_valid
rather than get_success_url
.
You should also have your clean function for “when” in the form and not perform any additional validation in the view. The form_valid
method should only be called once the entire form has been verified correct.
You can call super
in your form_valid
method and save the return value in a variable, update the objects, then return that saved value from your form_valid
method.
See the docs and examples at Many-to-many relationships | Django documentation | Django for working with ManyToManyFields.
Thank you, I’ve tidied up the form validation but I’m really sorry but I do not understand the part about
you can call super
in your form_valid
method and save the return value in a variable, update the objects, then return that saved value from your form_valid
method.
I have called the parent form_valid but I’m not sure how to access the objects and where do I return the value to from my form_valid?
class EventCreate(CreateView):
model = Event
initial = {}
form_class = EventCreateForm
def get_form(self, form_class=None):
form = super(EventCreate, self).get_form(form_class)
form.fields['association'].queryset = self.request.user.asc_access
form.fields['association'].initial = self.kwargs["association_id"]
form.fields['when'].widget = AdminDateWidget(attrs={'type': 'date'})
form.fields['time'].widget = AdminDateWidget(attrs={'type': 'time'})
return form
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
def form_valid(self, form):
super_resp = super().form_valid(form)
print(super_resp)
return super_resp
def get_success_url(self):
return reverse("showorderofplay:events", args=[self.kwargs["association_id"]])
class EventCreateForm(ModelForm):
class Meta:
model = Event
fields = ['name', 'when', 'time', 'description',
'active', 'cancelled', 'association']
labels = {'active': 'Published'}
def clean_when(self):
data = self.cleaned_data['when']
if data < timezone.localdate():
raise ValidationError(_('Date is in the past'))
return data
What you’ve got here is 100% the right idea. (Including the return super_resp
your form_valid
)
If you dig through the code for a CreateView (and the Classy Class-Based Views is a great tool for doing that), you’ll see that ModelFormMixin
has the line:
self.object = form.save()
This means that after super has been called, you can access the newly-created Event as self.object
.
(I also recommend getting familiar with the CBV diagrams page as well.)
So this is all I needed to do
def form_valid(self, form):
super_resp = super().form_valid(form)
self.request.user.event_access.add(self.object.id)
return super_resp
Thank you for your patience Ken, it must be frustrating at times having these sort of questions from inexpericienced programmers but your help is very gratefully received.