Je ne sais pas comment utiliser un ModelForm
dans un FormView
pour qu'il mette à jour une instance déjà existante ??
Les formulaires POST sur cette URL: r'/object/(?P<pk>)/'
J'utilise un ModelForm
(et pas directement un UpdateView
) car l'un des champs est obligatoire et j'effectue un nettoyage dessus.
Je voudrais essentiellement fournir le kwarg instance=...
lors de l'initialisation du formulaire dans le FormView
(au POST) afin qu'il soit lié à l'objet dont le pk est donné dans l'url. Mais je ne sais pas où faire ça ...
class SaveForm(ModelForm):
somedata = forms.CharField(required=False)
class Meta:
model = SomeModel # with attr somedata
fields = ('somedata', 'someotherdata')
def clean_somedata(self):
return sometransformation(self.cleaned_data['somedata'])
class SaveView(FormView):
form_class = SaveForm
def form_valid(self, form):
# form.instance here would be == SomeModel.objects.get(pk=pk_from_kwargs)
form.instance.save()
return ...
Après quelques discussions avec vous, je ne vois toujours pas pourquoi vous ne pouvez pas utiliser un UpdateView
. Cela semble être un cas d'utilisation très simple si je comprends bien. Vous avez un modèle que vous souhaitez mettre à jour. Et vous avez un formulaire personnalisé pour faire le nettoyage avant de l'enregistrer sur ce modèle. On dirait qu'un UpdateView
fonctionnerait très bien. Comme ça:
class SaveForm(ModelForm):
somedata = forms.CharField(required=False)
class Meta:
model = SomeModel # with attr somedata
fields = ('somedata', 'someotherdata')
def clean_somedata(self):
return sometransformation(self.cleaned_data['somedata'])
class SaveView(UpdateView):
template_name = 'sometemplate.html'
form_class = SaveForm
model = SomeModel
# That should be all you need. If you need to do any more custom stuff
# before saving the form, override the `form_valid` method, like this:
def form_valid(self, form):
self.object = form.save(commit=False)
# Do any custom stuff here
self.object.save()
return render_to_response(self.template_name, self.get_context_data())
Bien sûr, si je vous comprends mal, faites-le moi savoir. Vous devriez cependant pouvoir faire fonctionner cela.
Pour tous les autres visiteurs de ce fil, oui, vous pouvez créer un FormView
qui agit à la fois comme un CreateView
et un UpdateView
. Cela, malgré certaines opinions d'autres utilisateurs, peut avoir beaucoup de sens si vous voulez avoir un nique formulaire/URL/page pour un formulaire Web pour enregistrer certaines données utilisateur qui peuvent être facultatives mais doivent être sauvé une seule fois. Vous ne voulez pas avoir 2 URL/vues pour cela, mais juste une seule page/URL qui montre un formulaire, rempli de données précédentes à mettre à jour si un modèle a déjà été enregistré par l'utilisateur.
Pensez à une sorte de modèle "contact" comme celui-ci:
from Django.conf import settings
from Django.db import models
class Contact(models.Model):
"""
Contact details for a customer user.
"""
user = models.OneToOneField(settings.AUTH_USER_MODEL)
street = models.CharField(max_length=100, blank=True)
number = models.CharField(max_length=5, blank=True)
postal_code = models.CharField(max_length=7, blank=True)
city = models.CharField(max_length=50, blank=True)
phone = models.CharField(max_length=15)
alternative_email = models.CharField(max_length=254)
Donc, vous écrivez un ModelForm
pour cela, comme ceci:
from Django import forms
from .models import Contact
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
exclude = ('user',) # We'll set the user later.
Et votre FormView
avec les capacités "créer" et "mettre à jour" ressemblera à ceci:
from Django.core.urlresolvers import reverse
from Django.views.generic.edit import FormView
from .forms import ContactForm
from .models import Contact
class ContactView(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = reverse('MY_URL_TO_REDIRECT')
def get_form(self, form_class):
"""
Check if the user already saved contact details. If so, then show
the form populated with those details, to let user change them.
"""
try:
contact = Contact.objects.get(user=self.request.user)
return form_class(instance=contact, **self.get_form_kwargs())
except Contact.DoesNotExist:
return form_class(**self.get_form_kwargs())
def form_valid(self, form):
form.instance.user = self.request.user
form.save()
return super(ContactView, self).form_valid(form)
Vous n'avez même pas besoin d'utiliser un pk
dans l'URL de cet exemple, car l'objet est récupéré de la base de données via le champ un-à-un user
. Si vous avez un cas similaire à celui-ci, dans lequel le modèle à créer/mettre à jour a une relation unique avec l'utilisateur, c'est très simple.
J'espère que cela aide quelqu'un ...
À votre santé.
Vous pouvez utiliser la méthode post de FormView pour obtenir les données publiées et les enregistrer dans le modèle à l'aide de form.save (). J'espère que cela vous aidera.
Essaye ça
class SaveForm(ModelForm):
somedata = forms.CharField(required=False)
class Meta:
model = SomeModel # with attr somedata
fields = ('somedata', 'someotherdata')
def __init__(self, *args, **kwargs):
super(SaveForm, self).__init__(*args, **kwargs)
def save(self, id):
print id #this id will be sent from the view
instance = super(SaveForm, self).save(commit=False)
instance.save()
return instance
class SaveView(FormView):
template_name = 'sometemplate.html'
form_class = SaveForm
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
form.save(kwargs.get('pk'))
else:
return self.form_invalid(form)