i am using django formset to save multiple form at a time.but data is not saving in my database.I am using class based views.This is the model where i want to save my data.
Model
class Period(AbstractBaseModel):
validators = [ScreenMethodValidator, ChainIntegrityValidator]
chain = models.ForeignKey(
'customers.Chain',
help_text=_('chain to which period belongs to'),
verbose_name=_('chain')
)
start_date = models.DateTimeField(
default=datetime.datetime.now,
help_text=_('Starting date of a period'),
verbose_name=_('start date')
)
end_date = models.DateTimeField(
default=datetime.datetime(1970, 01, 01),
help_text=_('Ending date of a period'),
verbose_name=_('end date')
)
year = models.IntegerField(
default=0,
help_text=_('Financial year'),
verbose_name=_('year'),
null=True,blank=True
)
description = models.TextField(
help_text=_('Description of a period'),
verbose_name=_('description'),
null=True,blank=True
)
class Meta:
app_label = 'accounting'
and View
class PeriodCreate(RequestPassingFormViewMixin, WammuCreateView):
model = Chain
template_name = 'dashboard/period_form.html'
form_class = ChainForm
def get_object(self):
chain = Chain.objects.get(pk=self.kwargs['chain_pk'])
return chain
def get_success_url(self):
return reverse('dashboard_period_list', kwargs={'chain_pk': self.object.chain.id, })
def get_context_data(self, **kwargs):
context = super(PeriodCreate, self).get_context_data(**kwargs)
return context
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(PeriodCreate, self).get_form_kwargs(*args, **kwargs)
chain = get_object_or_404(Chain, pk=self.kwargs['chain_pk'])
period = Period(chain=chain)
kwargs['instance'] = period
return kwargs
def get(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
PeriodInlineFormSet = inlineformset_factory(Chain, Period,
form=PeriodInlineForm,
can_delete=True,
extra=12)
PeriodInlineFormSet.form = staticmethod(curry(PeriodInlineForm, request=request, chain=self.object))
period_formset = PeriodInlineFormSet()
return self.render_to_response(
self.get_context_data(form=form,
period_inline_formset=period_formset))
def post(self, request, *args, **kwargs):
self.object = Chain()
form = self.get_form(self.form_class)
PeriodInlineFormSet = inlineformset_factory(Chain, Period,
form=PeriodInlineForm,
can_delete=True,
extra=12)
PeriodInlineFormSet.form = staticmethod(curry(PeriodInlineForm))
if form.is_valid():
self.object = form.save(commit=False)
period_formset = PeriodInlineFormSet(request.POST, instance=self.object)
if period_formset.is_valid():
self.object.save()
period_formset.save()
return super(PeriodCreate, self).form_valid(form)
else:
return self.render_to_response(
context=self.get_context_data(form=form, period_inline_formset=period_formset))
else:
period_formset = PeriodInlineFormSet(request.POST,instance=self.object)
return self.render_to_response(
context=self.get_context_data(form=form, period_inline_formset=period_formset))
and use the following link to see my other code related to this issue where i have tried to use django formset and faced an argument error which has been solved
but now data is not saving in data base when i am trying to post data.surely the error is occurring in my post method,but as i am not used to work with django formset,i can't figure it out after a long findings.
django __init__ method causing argument error
Related
The objective is to have a simple workflow where an order and associated orderlines (created in a previous step) needs to be approved by the relevant budget holder. The approval form shows all order lines but disables those lines that the current user is not associated with (they should be able to see the overall order but only be able to edit lines that they are permitted to). They should be able to add new lines if necessary. The user needs to decide whether to approve or not (approval radio cannot be blank)
The initial form presents correctly and is able to save inputs correctly when all values are inputted correctly - however, if it fails validation then the incorrect fields get highlighted and their values are cleared.
models.py
class Order(models.Model):
department = models.ForeignKey(user_models.Department, on_delete=models.CASCADE)
location = models.ForeignKey(location_models.Location, on_delete=models.CASCADE, null=True)
description = models.CharField(max_length=30)
project = models.ForeignKey(project_models.Project, on_delete=models.CASCADE)
product = models.ManyToManyField(catalogue_models.Product, through='OrderLine', related_name='orderlines')
total = models.DecimalField(max_digits=20, decimal_places=2, null=True, blank=True)
def __str__(self):
return self.description
class OrderLine(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
project_line = models.ForeignKey(project_models.ProjectLine, on_delete=models.SET_NULL, null=True, blank=False)
product = models.ForeignKey(catalogue_models.Product, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
price = models.DecimalField(max_digits=20, decimal_places=4)
total = models.DecimalField(max_digits=20, decimal_places=2)
budgetholder_approved = models.BooleanField(null=True)
def get_line_total(self):
total = self.quantity * self.price
return total
def save(self, *args, **kwargs):
self.total = self.get_line_total()
super(OrderLine, self).save(*args, **kwargs)
def __str__(self):
return self.product.name
views.py
class BudgetApprovalView(FlowMixin, generic.UpdateView):
form_class = forms.BudgetHolderApproval
def get_object(self):
return self.activation.process.order
def get_context_data(self, **kwargs):
data = super(BudgetApprovalView, self).get_context_data(**kwargs)
if self.request.POST:
data['formset'] = forms.OrderLineFormet(self.request.POST, instance=self.object)
else:
data['formset'] = forms.OrderLineFormet(instance=self.activation.process.order, form_kwargs={'user': self.request.user})
return data
def post(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
form = forms.BudgetHolderApproval(self.request.POST, instance=self.activation.process.order)
formset = forms.OrderLineFormet(self.request.POST, instance=self.activation.process.order)
if form.is_valid() and formset.is_valid():
return self.is_valid(form, formset)
else:
return self.is_invalid(form, formset)
def is_valid(self, form, formset):
self.object = form.save(commit=False)
self.object.created_by = self.request.user
self.activation.process.order = self.object
with transaction.atomic():
self.object.save()
self.activation.done()
formset.save()
return HttpResponseRedirect(self.get_success_url())
def is_invalid(self, form, formset):
return self.render_to_response(self.get_context_data(form=form, formset=formset))
I have tried a couple of things to figure this out - without success:
to override the clean() method of the ModelForm - however, I cannot figure out how to determine if the submitted form is disabled or not.
forms.py
class OrderForm(forms.ModelForm):
class Meta:
model = models.Order
fields = ['description', 'project', 'location']
def __init__(self, *args, **kwargs):
super(OrderForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
class OrderLine(forms.ModelForm):
class Meta:
model = models.OrderLine
exclude = ['viewflow']
def __init__(self, *args, **kwargs):
YES_OR_NO = (
(True, 'Yes'),
(False, 'No')
)
self.user = kwargs.pop('user', None)
super(OrderLine, self).__init__(*args, **kwargs)
self.fields['project_line'].queryset = project_models.ProjectLine.objects.none()
self.fields['budgetholder_approved'].widget = forms.RadioSelect(choices=YES_OR_NO)
if self.instance.pk:
self.fields['budgetholder_approved'].required = True
self.fields['order'].disabled = True
self.fields['project_line'].disabled = True
self.fields['product'].disabled = True
self.fields['quantity'].disabled = True
self.fields['price'].disabled = True
self.fields['total'].disabled = True
self.fields['budgetholder_approved'].disabled = True
if 'project' in self.data:
try:
project_id = int(self.data.get('project'))
self.fields['project_line'].queryset = project_models.ProjectLine.objects.filter(project_id=project_id)
except (ValueError, TypeError):
pass
elif self.instance.pk:
self.fields['project_line'].queryset = self.instance.order.project.projectline_set
project_line_id = int(self.instance.project_line.budget_holder.id)
user_id = int(self.user.id)
if project_line_id == user_id:
self.fields['budgetholder_approved'].disabled = False
self.helper = FormHelper()
self.helper.template = 'crispy_forms/templates/bootstrap4/table_inline_formset.html'
self.helper.form_tag = False
def clean(self):
super(OrderLine, self).clean()
pprint(vars(self.instance))
//This just returns a list of fields without any attributes to apply the validation logic
OrderLineFormet = forms.inlineformset_factory(
parent_model=models.Order,
model=models.OrderLine,
form=OrderLine,
extra=2,
min_num=1
)
to override the clean() method of the BaseInlineFormSet - however, I cannot disable the fields in the init or any of the validation rules (it silently fails validation and presents a blank inlineformset on failure - it never gets to clean() method.
forms.py
class OrderForm(forms.ModelForm):
class Meta:
model = models.Order
fields = ['description', 'project', 'location']
def __init__(self, *args, **kwargs):
super(TestOrderForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
class BaseTestOrderLine(forms.BaseInlineFormSet):
def __init__(self, user, *args, **kwargs):
self.user = user
super(BaseTestOrderLine, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.template = 'crispy_forms/templates/bootstrap4/table_inline_formset.html'
self.helper.form_tag = False
// Never gets to the clean method as is_valid fails silently
def clean(self):
super(BaseTestOrderLine, self).clean()
if any(self.errors):
pprint(vars(self.errors))
return
OrderLineFormet = forms.inlineformset_factory(
parent_model=models.Order,
model=models.OrderLine,
formset=BaseTestOrderLine,
exclude=['order'],
extra=2,
min_num=1
)
Edit - reflecting progress based on Dao's suggestion (the form reloads correctly with the validation errors showing correctly)
The only remaining problem is that when the form reloads - the field (budgetholder_approved) that should still be enabled is disabled. One of the two approval checkbox lines lines should be editable
Looks like because you have different formset context data on submit invalid
if self.request.POST:
data['formset'] = forms.OrderLineFormet(self.request.POST, instance=self.activation.process.order, form_kwargs={'user': self.request.user})
else:
data['formset'] = forms.OrderLineFormet(instance=self.activation.process.order, form_kwargs={'user': self.request.user})
return data
Edit for updated Q:
Didn't test this out because of time constraint but because you already initiated the field and overwrite the widget, so if you need to update disabled attr of widget instead of field.
self.fields['budgetholder_approved'].widget = forms.RadioSelect(choices=YES_OR_NO)
self.fields['budgetholder_approved'].widget.attrs['disabled'] = False
I got a tracking model, and an evidence model wit ha foreign to it. Im trying to upload a file in evidence related to that tracking...but when i try to save i got this error:
Request Method: POST
Request URL: http://127.0.0.1:8000/myapp/change_actions/tracking/create/1/
Django Version: 1.10.1
Exception Type: RelatedObjectDoesNotExist
Exception Value:
Evidence has no tracking.
My view saves tracking form and then passes the id of that record to the evidence form as foreign.....but that error is like the form was eliminating the tracking field !!....these are my files :
Models.py
class Tracking(ModelBase):
activity = models.ForeignKey(
Activity,
verbose_name = 'Actividad', null = False)
code = models.CharField('Codigo de seguimiento', max_length=50)
observation = models.TextField('Avance a la fecha', max_length=2000)
tracking_date = models.DateTimeField('Fecha de seguimiento')
def __str__(self):
return self.observation
class Evidence(ModelBase):
tracking = models.ForeignKey(
Tracking,
related_name = 'Tracking_evidence',
verbose_name = 'Seguimiento', null = False)
evidence = models.FileField(verbose_name = 'Evidencia', null = True, upload_to='documents/')
This is the form.py:
class EvidenceForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.tracking = kwargs.pop('tracking')
super(EvidenceForm, self).__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
cleaned_data = super(EvidenceForm, self).clean()
self.instance.tracking.id = self.tracking
class Meta:
model = Evidence
fields = ['tracking', 'evidence']
And the view to it :
class TrackingCreateView(View):
template_name = ['change_actions/tracking_create.html']
breadcrumb = [{'name': 'Registro de seguimiento', 'url': None}]
#method_decorator(login_required)
def get(self, request, *args, **kwargs):
form = TrackingForm()
form_evidence = EvidenceForm(tracking = None)
activity = Activity.objects.get(pk = kwargs['activity_id'])
return render(request, self.template_name,{
'form_tracking': form,'breadcrumb': self.breadcrumb,
'activity': activity,'form_evidence': form_evidence})
def post(self, request, *args, **kwargs):
form = TrackingForm(request.POST)
activity = Activity.objects.get(pk = request.POST['activity_id'])
self.breadcrumb[0]['url'] = reverse(
'change_actions:tracking_create',
kwargs = {'activity_id': activity.id })
context = {
'breadcrumb': self.breadcrumb, 'activity': activity,
'form_tracking': form}
if form.is_valid():
form.save()
form_evidence = EvidenceForm(
request.POST, request.FILES, tracking = form.instance.id)
if form_evidence.is_valid():
form_evidence.save()
messages.success(request, 'Seguimiento registrado correctamente')
return HttpResponseRedirect(reverse(
'change_actions:activity_detail',
kwargs = {'activity_id': activity.id }))
else:
context.update({'form_evidence': form_evidence})
return render(request, self.template_name, context)
else:
context['form_tracking'] = form
return render(request, self.template_name, context)
Any idea why I am getting this error? Thanks in advance!
I have been Googling around for this question for quite long. And sadly no luck. Indeed I found questions like SO question and SO question. I would say I found myself having a very similar question to the first one. However, I do not understand the discussions under that question.
So first of all, to make it clear, I did not even get formset.is_valid() to return True--that is the problem. There are indeed uniqueness check but my edit should be able to pass that check in the database level.
And here comes my code:
### models.py
class DataAccess(models.Model):
user = models.ForeignKey(User, models.CASCADE)
project_data = models.ForeignKey(ProjectData, models.CASCADE)
role = models.CharField(
max_length=2, choices=ROLES, default='N'
)
created_at = models.DateTimeField(auto_now=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
unique_together = (('user', 'project_data', 'role'),)
# query from project data should happen more
index_together = [['project_data', 'user', 'role']]
def __str__(self):
return '{}&{}&{}'.format(self.user, self.project_data, self.role)
def save(self, *args, **kwargs):
curr = datetime.now()
if not self.created_at:
self.created_at = curr
self.updated_at = curr
return super(DataAccess, self).save(*args, **kwargs)
class DataSyncPath(models.Model):
server = models.ForeignKey(Server, models.CASCADE)
project_data = models.ForeignKey(ProjectData, models.CASCADE)
path = models.CharField(max_length=128)
created_at = models.DateTimeField(auto_now=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
unique_together = (('server', 'project_data',),)
index_together = [['project_data', 'server']]
def __str__(self):
return '{}&{}'.format(self.server, self.project_data)
def save(self, *args, **kwargs):
curr = datetime.now()
if not self.created_at:
self.created_at = curr
self.updated_at = curr
return super(DataSyncPath, self).save(*args, **kwargs)
### forms.py
class DataAccessForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DataAccessForm, self).__init__(*args, **kwargs)
helper = FormHelper()
helper.template = 'bootstrap/table_inline_formset.html'
self.helper = helper
self.helper.form_tag = False
class Meta:
model = DataAccess
exclude = ['created_at', 'updated_at']
def get_data_access_formset(initial=[], extra=3):
return inlineformset_factory(
ProjectData, DataAccess,
form=DataAccessForm, extra=extra + len(initial)
)
class DataSyncPathForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DataSyncPathForm, self).__init__(*args, **kwargs)
helper = FormHelper()
helper.template = 'bootstrap/table_inline_formset.html'
self.helper = helper
self.helper.form_tag = False
class Meta:
model = DataSyncPath
exclude = ['created_at', 'updated_at']
def clean(self):
super(DataSyncPathForm, self).clean()
if (self.cleaned_data['id'] is None and 'path' in self.errors and
self.errors['path'][0] == 'This field is required.'):
# a special hack to silent path error
self.errors.pop('path')
def get_data_sync_path_formset(initial=[], extra=0):
return inlineformset_factory(
ProjectData, DataSyncPath, can_delete=False,
form=DataSyncPathForm, extra=extra + len(initial)
)
### views.py, import and everything is taken care of already
class ProjectDataUpdateView(LoginRequiredMixin, UpdateView):
login_url = reverse_lazy('login')
redirect_field_name = 'redirect_to'
template_name = 'project_data/project_data_form.html'
form_class = ProjectDataForm
context_object_name = 'project_data'
pk_url_kwarg = 'project_data_id'
success_url = reverse_lazy('data_projects:project_data_list')
def get_queryset(self):
return dbmanager.get_project_data_by_user(
self.request.user
)
def get_initial(self):
initial = super(ProjectDataUpdateView, self).get_initial()
try:
initial['phabricator_links'] = ','.join(json.loads(
self.object.phabricator_links))
except Exception:
initial['phabricator_links'] = ''
return initial
def get_data_access_initial(self):
data_access_queryset = self.object.dataaccess_set.all()
data_access_initial = [
model_to_dict(obj) for obj in data_access_queryset
]
return data_access_initial
def get_data_sync_path_initial(self):
datasyncpath_set = self.object.datasyncpath_set.all()
sync_path_initial = [
model_to_dict(obj) for obj in datasyncpath_set
]
servers = self.request.user.server_set.all()
missing_servers = set(
[server.id for server in servers]) - set(
[obj['server'] for obj in sync_path_initial]
)
for server_id in missing_servers:
sync_path_initial.append({'server': server_id})
return sync_path_initial
def process_context_data(self, data):
data_access_initial = self.get_data_access_initial()
sync_path_initial = self.get_data_sync_path_initial()
if self.request.POST:
if (self.request.user.is_superuser or
self.request.user.groups.filter(name='Manager').exists()):
data['data_access_formset'] = get_data_access_formset()(
self.request.POST, self.request.FILES,
instance=self.object, initial=data_access_initial,
queryset=self.object.dataaccess_set.all()
)
data['data_sync_path_formset'] = get_data_sync_path_formset()(
self.request.POST, self.request.FILES,
instance=self.object, initial=sync_path_initial,
queryset=self.object.datasyncpath_set.all()
)
else:
data['data_access_formset'] = get_data_access_formset(
initial=data_access_initial
)(initial=data_access_initial)
data['data_sync_path_formset'] = get_data_sync_path_formset(
initial=sync_path_initial
)(initial=sync_path_initial)
return data
def get_context_data(self, **kwargs):
data = super(ProjectDataUpdateView, self).get_context_data(**kwargs)
data_access_formset = kwargs.pop('data_access_formset', None)
data_sync_path_formset = kwargs.pop('data_sync_path_formset', None)
if data_access_formset and data_sync_path_formset:
data['data_access_formset'] = data_access_formset
data['data_sync_path_formset'] = data_sync_path_formset
else:
data = self.process_context_data(data)
data['is_data_sync_path_set'] = True
return data
def post(self, request, *args, **kwargs):
self.object = self.get_object()
if not (self.request.user.is_superuser or
self.request.user.groups.filter(name='Manager').exists()):
self.request.POST['name'] = self.object.name
self.request.POST['dmgr'] = self.object.dmgr
form_class = self.get_form_class()
form = self.get_form(form_class)
context_data = self.get_context_data()
data_access_formset = context_data.get('data_access_formset')
sync_path_formset = context_data.get('data_sync_path_formset')
if (form.is_valid() and
data_access_formset.is_valid() and
sync_path_formset.is_valid()):
return self.form_valid(
form, data_access_formset, sync_path_formset)
else:
return self.form_invalid(
form, data_access_formset, sync_path_formset)
def form_valid(
self, form, data_access_formset, sync_path_formset, **kwargs):
for deleted_form in data_access_formset.deleted_forms:
try:
deleted_form.cleaned_data['id'].delete()
except Exception:
pass
self.object = form.save()
data_access_formset.save()
sync_path_formset.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(
self, form, data_access_formset, sync_path_formset, **kwargs):
return self.render_to_response(
self.get_context_data(
form=form, data_access_formset=data_access_formset,
sync_path_formset=sync_path_formset
)
)
I have also put breakpoint in post method of the UpdateView class:
ipdb> sync_path_formset.is_valid()
False
ipdb> sync_path_formset.forms[0]
<DataSyncPathForm bound=True, valid=False, fields=(server;project_data;path;id;DELETE)>
ipdb> sync_path_formset.forms[0].cleaned_data
{'DELETE': False, 'project_data': <ProjectData: bbb>, 'path': 'that', 'server': <Server: jgu-pc>, 'id': <DataSyncPath: jgu-pc&bbb>}
ipdb> sync_path_formset.forms[0].instance
<DataSyncPath: jgu-pc&bbb>
ipdb> sync_path_formset.forms[0].save(commit=False)
*** ValueError: The DataSyncPath could not be created because the data didn't validate.
ipdb> sync_path_formset.forms[0].has_changed()
True
So clearly the instance exists. But it just tries to create another instance anyway.
I have trouble getting the current instance's fields on my UpdateView. How do I get the specific instance based on its id?
views.py
class ShowUpdate(UpdateView):
model = Show
fields = ['description', 'season', 'episode']
def post(self, request, **kwargs):
request.POST = request.POST.copy()
request.POST['description'] = "how to get instance description?" # problem here
request.POST['season'] = 2
return super(ShowUpdate, self).post(request, **kwargs)
models.py
class Show(models.Model):
owner = models.ForeignKey(User, null=True, default=True, related_name='o')
title = models.CharField(max_length=100)
description = models.TextField(default='N/A', blank=True, max_length=250)
season = models.IntegerField(default=0)
episode = models.IntegerField(default=0)
def get_absolute_url(self):
return reverse('show:index')
def __str__(self):
return self.title
Look to the UpdateView docs
This View has method get_object(self, queryset=None)
In you case just need to call it in POST method something like this:
class ShowUpdate(UpdateView):
model = Show
fields = ['description', 'season', 'episode']
def post(self, request, **kwargs):
self.object = self.get_object()
request.POST = request.POST.copy()
request.POST['description'] = self.object.description
request.POST['season'] = 2
return super(ShowUpdate, self).post(request, **kwargs)
My form isn't saving the models that I need it to. My form:
class RewardForm(forms.Form):
quantity = forms.IntegerField(max_value=10, min_value=1, label=_('quantity'), initial=1)
reward = forms.CharField(max_length=50, label=_('reward'))
reward_denomination = forms.ModelChoiceField(queryset=Reward_Denomination.objects.all(), widget=forms.RadioSelect)
def clean_reward(self):
data = self.cleaned_data.get('reward')
try:
reward = Reward.objects.get(reward_name=data)
except ObjectDoesNotExist:
raise forms.ValidationError(_('Reward does not exist'), code='invalid')
return data
def clean_reward_denomination(self):
data = self.cleaned_data.get('reward_denomination')
try:
denomination = Reward_Denomination.objects.get(denomination=data)
except ObjectDoesNotExist:
raise forms.ValidationError(_('Denomination does not exist'), code='invalid')
return data
def save(self, request, commit=True):
user = request.user
data = self.cleaned_data
'try:
post_reward = data['reward']
post_denomination = data['reward_denomination']
quantity = data['quantity']
except LookupError:
raise Http404
reward = Reward.objects.get(reward_name=post_reward)
denomination = Reward_Denomination.objects.get(denomination=post_denomination)
user_points = Points.objects.filter(affiliate__id=user.id).aggregate(total_points=Sum('points'))
user_points = user_points['total_points']
try:
total_cost = (quantity * denomination.cost)
except ArithmeticError:
raise Http404
quote_price = -total_cost
if user_points >= total_cost:
reward_order = Points.objects.create(affiliate=user, points=quote_price, from_reward=True, from_offer=False)
status_coded = Status_Code.objects.create(short_name="Pending", name="The order is currently being reviewed", description="The order is in queue")
redeem_order = Redeem.objects.create(affiliate=user, status_code=status_coded, quantity=quantity, reward=reward, price=total_cost)
return reward_order
My Views:
class Reward_Detail(DetailView):
model = Reward
slug_field = 'reward_slug'
context_object_name = 'reward'
template_name = 'omninectar/reward.html'
#Detail Stuff
class RedeemReward(SingleObjectMixin, FormView):
template_name = 'omninectar/reward.html'
slug_field = 'reward_slug'
form_class = RewardForm
model = Reward
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super(RedeemReward, self).post(request, *args, **kwargs)
def get_success_url(self):
return reverse('omni:reward_confirmation')
class RewardBeautify(View):
def get(self, request, *args, **kwargs):
view = Reward_Detail.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = RedeemReward.as_view()
return view(request, *args, **kwargs)
So I initially thought that the FormView would handle the form processing (validate, and, if valid, run form.save(), etc). I'm following the FormView, SingleObjectMixin example on the Django website. I don't receive any errors when I try and submit the form, but no objects are created either. I've tried defining a form_valid method that runs the save method, I've tried putting it inside the post method in the formview, etc. Can anyone spot the error/errors? Thanks!
I'm new to view classes too and I had almost the same problem with Django 1.6.
You should add
def form_valid(self, form):
form.save()
return super(RedeemReward, self).form_valid(form)
method overriding to your RedeemReward class. This worked for me.
If you look to Django source code, you will see that there is no form saving in FormView class inheritance chain.
I am not sure if this will help or not, but I had issues finding code showing how to save the data from a FormView model. This is what I came up with. I hope it helps and you can apply it to your code.
forms.py
class JobCreateForm(forms.Form):
title = forms.CharField(label='Job Title', max_length=500)
number = forms.IntegerField(label='Job Number: ')
comps = forms.ModelMultipleChoiceField(label='Comparable Sales',
required=False, queryset=m.ComparableSale.objects.all())
details = forms.CharField(label='Job Details:', max_length=200,
required=False, widget=forms.Textarea(attrs={'rows':6, 'cols':20}))
Views.py
class JobCreateView(generic.FormView):
template_name = 'form_templates/createjob_form.html'
form_class = f.JobCreateForm
model = models.Job
success_url = '/'
def form_valid(self, form):
comps = form.cleaned_data['comps']
title = form.cleaned_data['title']
number = form.cleaned_data['number']
details = form.cleaned_data['details']
job = models.Job(title=title, number=number, details=details)
job.save()
print(comps)
if comps != []:
job.comps.add(*comps)
return super(JobCreateView, self).form_valid(form)
You can write your own ModelFormView using the mixins provided by Django (specifically, the ModelFormMixin). Then your form will be saved on a successful post.
from django.views.generic.base import TemplateResponseMixin
from django.views.generic.edit import ModelFormMixin, ProcessFormView
class BaseModelFormView(ModelFormMixin, ProcessFormView):
pass
class ModelFormView(TemplateResponseMixin, BaseModelFormView):
pass