11👍
…
if form.is_valid():
client_mod = form.save(commit=False)
client_mod.save()
for groupe in form.cleaned_data.get('groupes'):
clientgroupe = ClientGroupe(client=client_mod, groupe=groupe)
clientgroupe.save()
…
18👍
If you use the save method right now, Django will try to save using the manager (which Django doesn’t allow). Unfortunately, the behavior you want is a little bit trickier than what ModelForm
does by default. What you need to do is create a formset.
First of all, you will need to change the options of your ClientForm
so that it doesn’t display the groupes
attribute.
class ClientForm(ModelForm):
class Meta:
model = Client
exclude = ('groupes',)
Next, you must change the view to display the formset:
from django.forms.models import inlineformset_factory
def modifier(request, id):
client = Client.objects.get(id=id)
form = ClientForm(instance = client)
# Create the formset class
GroupeFormset = inlineformset_factory(Client, Groupe)
# Create the formset
formset = GroupeFormset(instance = client)
dict = {
"form": form
, "formset" : formset
, "instance" : client
}
if request.method == "POST":
form = ClientForm(request.POST, instance = client)
formset = GroupeFormset(request.POST, instance = client)
if form.is_valid() and formset.is_valid():
client_mod = form.save()
formset.save()
id = client_mod.id
return HttpResponseRedirect(
"/client/%(id)s/?err=success" % {"id" : id}
)
else:
return HttpResponseRedirect(
"/client/%(id)s/?err=warning" % {"id" : id}
)
return render_to_response(
"client/modifier.html"
, dict
, context_instance=RequestContext(request)
)
And obviously, you must also tweak your template to render the formset.
If you need any other advice on formsets, see these articles:
- [Django]-How do I input HTML into the help text of a Django form field?
- [Django]-Include intermediary (through model) in responses in Django Rest Framework
- [Django]-Union and Intersect in Django
4👍
You probably need to remove the ManyToMany field from your Client model, or else carefully exclude it from your form. Unfortunately, the default widget for the ManyToMany field cannot populate the ClientGroupe Model properly (even if the missing field, dt, had been set to autonow=True). This is something you’ll either need to break out into another form, or handle in your view.
- [Django]-Django model instances primary keys do not reset to 1 after all instances are deleted
- [Django]-Select between two dates with Django
- [Django]-Request.POST.get('sth') vs request.POST['sth'] – difference?
0👍
When you save your form, you save Client object. Now if you want to assign client to the group you should do this:
clientgroupe = ClientGroupe.objects.create(client=client_instance, groupe=groupe_instance, dt=datetime.datetime.now())
where client_instance and groupe_instance your client and groupe objets.
- [Django]-Django: list all reverse relations of a model
- [Django]-How to test Django's UpdateView?
- [Django]-Django multiprocessing and database connections
-1👍
I’m providing an alternative solution due to issues I encountered with forms_valid not being called:
class SplingCreate(forms.ModelForm):
class Meta:
model = SplingModel
fields = ('Link', 'Genres', 'Image', 'ImageURL',)
def save(self, commit=True):
from django.forms.models import save_instance
if self.instance.pk is None:
fail_message = 'created'
else:
fail_message = 'changed'
fields = set(self._meta.fields) - set(('Genres',))
instance = save_instance(self, self.instance, fields,
fail_message, commit, construct=False)
genres = self.cleaned_data.get('Genres')
for genre in genres:
SplingGenreModel.objects.get_or_create(spling=instance, genre=genre)
return instance
I’ve copied the logic from djangos forms/models.py, my field Genres is a manytomany with an intermediary table – I exclude it from the save_instance and then save it separately.
- [Django]-How to copy modules from one virtualenv to another
- [Django]-Django middleware difference between process_request and process_view
- [Django]-Change Django ModelChoiceField to show users' full names rather than usernames