formmodel - formularios django
Django: Inicializando un FormSet de formularios personalizados con instancias (2)
El truco es usar un "ModelFormset" en lugar de solo un formset, ya que permiten la inicialización con un queryset. Los documentos están here , lo que hace es proporcionar un formulario = * cuando crea el modelo formset y queryset = * cuando crea una instancia del formulario. El argumento de form = * no está bien documentado (tuvo que indagar un poco en el código para asegurarse de que realmente está allí).
def edit(request):
PointFormSet = modelformset_factory(Point, form = PointForm)
qset = Point.objects.all() #or however your getting your Points to modify
formset = PointFormset(queryset = qset)
if request.method == ''POST'':
#deal with posting the data
formset = PointFormset(request.POST)
if formset.is_valid():
#if it is not valid then the "errors" will fall through and be returned
formset.save()
return #to your redirect
context_dict = {''formset'':formset,
#other context info
}
return render_to_response(''your_template.html'', context_dict)
Así que el código camina fácilmente. Si la solicitud es un GET, la forma instanciada se devuelve al usuario. Si la solicitud es un POST y el formulario not .is_valid()
es not .is_valid()
, los errores "fallan" y se devuelven en la misma plantilla. Si la solicitud es un POST y los datos son válidos, entonces se guarda el formset.
Espero que ayude.
-Será
Dados los siguientes modelos:
class Graph(models.Model):
owner = models.ForeignKey(User)
def __unicode__(self):
return u''%d'' % self.id
class Point(models.Model):
graph = models.ForeignKey(Graph)
date = models.DateField(primary_key = True)
abs = models.FloatField(null = True)
avg = models.FloatField(null = True)
def __unicode__(self):
return u''%s'' % self.date
Estoy tratando de crear un formulario para editar listas de puntos. Las etiquetas de entrada HTML requieren atributos adicionales para configurarse, por lo que estoy usando el siguiente formulario personalizado:
class PointForm(forms.ModelForm):
graph = forms.ModelChoiceField(queryset = Graph.objects.all(),
widget = forms.HiddenInput())
date = forms.DateField(widget = forms.HiddenInput(), label = ''date'')
abs = forms.FloatField(widget = forms.TextInput(
attrs = {''class'': ''abs-field''}),
required = False)
class Meta:
model = Point
fields = (''graph'', ''date'', ''abs'') # Other fields are not edited.
def pretty_date(self):
return self.data.strftime(''%B'')
En este punto, no sé cómo pasar instancias de la clase Point a un FormSet:
def edit(request):
PointFormSet = forms.formsets.formset_factory(PointForm, extra = 0)
if request.method == ''POST'':
return
# Receive 3 points to edit from the database.
graph, res = Graph.objects.get_or_create(id = 1)
one_day = datetime.timedelta(days = 1)
today = datetime.date.today()
do_edit = []
for date in [today - (x * one_day) for x in range(3)]:
point, res = Point.objects.get_or_create(graph = graph, date = date)
do_edit.append(point)
formset = PointFormSet(????) # How is this initialized with the points?
Encontré un truco que funciona, pero conduce a errores más adelante al intentar procesar los datos POST resultantes:
do_edit = []
for date in [today - (x * one_day) for x in range(3)]:
point, res = Point.objects.get_or_create(graph = graph, date = date)
data = point.__dict__.copy()
data[''graph''] = graph
do_edit.append(data)
formset = PointFormSet(initial = do_edit)
¿Cómo se hace esto correctamente?
Para la referencia, mi plantilla se ve así:
<form action="" method="post">
{{ formset.management_form }}
<table>
<tbody>
{% for form in formset.forms %}
<tr>
<td>{{ form.graph }} {{ form.date }} {{ form.pretty_date }}:</td>
<td width="100%">{{ form.abs }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
Si solo tiene un valor posible que desea establecer, o tal vez un valor cerrado, es posible establecerlos después de que el usuario PERMITE los datos en su servidor usando commit=False
Por favor considere el siguiente código:
class UserReferralView(View):
ReferralFormSet = modelformset_factory(ReferralCode,
form=ReferralTokenForm, extra=1)
def get(self, request):
pass
def post(self, request):
referral_formset = UserUpdateView.ReferralFormSet(request.POST)
if referral_formset.is_valid():
instances = referral_formset.save(commit=False)
for instance in instances:
instance.user = request.user
instance.save()
return redirect(reverse(''referrals.success_view''))
else:
return redirect(reverse(''referrals.failure_view''))