问题
i want to get in inline formset factory in update view extra=0
, if it have more than 1 contact. So this is my code
forms.py
class ShopForm(ModelForm):
class Meta:
model = Shop
exclude = ['user', 'slug', 'counter']
def __init__(self, *args, **kwargs):
super(ShopForm, self).__init__(*args, **kwargs)
for field in iter(self.fields):
self.fields[field].widget.attrs.update({
'class': 'form-control'
})
def clean_logo(self):
logo = self.cleaned_data['logo']
if not logo:
raise forms.ValidationError("Логотип обязателен для заполнения", code='no_logo')
return logo
ShopInlineFormSet = inlineformset_factory(Shop, Contacts, extra=1,
fields=(
'published', 'phone', 'address', 'place', 'latitude',
'longitude', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday',
'saturday', 'sunday'), can_delete=True)
models.py
class Shop(PublishBaseModel, Counter):
class Meta:
verbose_name = 'Магазин'
verbose_name_plural = 'Магазины'
user = models.ManyToManyField(to=User, verbose_name='Администратор магазина')
title = models.CharField(max_length=255, verbose_name='Название магазина')
slug = models.CharField(max_length=32, verbose_name='Название на транслите', unique=True)
email = models.EmailField(verbose_name='E-mail магазина')
short_description = models.TextField(verbose_name='Короткое описание магазина')
description = models.TextField(verbose_name='Полное описание магазина')
logo = models.ImageField(upload_to='images/shop/logo/', default=settings.DEFAULT_IMAGE,
verbose_name='Логотип')
class Contacts(PublishBaseModel):
class Meta:
verbose_name = 'Контакт'
verbose_name_plural = 'Контакты'
address = models.CharField(verbose_name='Адрес', max_length=255, null=True, blank=True)
phone = models.CharField(max_length=255, verbose_name='Телефон', null=True, blank=True)
shop = models.ForeignKey(Shop, verbose_name='Магазин', null=True)
place = models.ForeignKey('Place', verbose_name='Торговая точка', null=True, blank=True)
latitude = models.CharField(max_length=255, verbose_name='Широта', null=True, blank=True)
longitude = models.CharField(max_length=255, verbose_name='Долгота', null=True, blank=True)
monday = models.CharField(max_length=255, verbose_name='Понедельник', null=True, blank=True)
tuesday = models.CharField(max_length=255, verbose_name='Понедельник', null=True, blank=True)
wednesday = models.CharField(max_length=255, verbose_name='Понедельник', null=True, blank=True)
thursday = models.CharField(max_length=255, verbose_name='Понедельник', null=True, blank=True)
friday = models.CharField(max_length=255, verbose_name='Понедельник', null=True, blank=True)
saturday = models.CharField(max_length=255, verbose_name='Понедельник', null=True, blank=True)
sunday = models.CharField(max_length=255, verbose_name='Понедельник', null=True, blank=True)
views.py
class ShopCreateView(LoginRequiredMixin, FormsetMixin, CreateView):
form_class = ShopForm
formset_class = ShopInlineFormSet
model = Shop
template_name = 'shop/shop_form.html'
def get_success_url(self):
return reverse('shops:detail', args=(self.object.slug,))
def form_valid(self, form, formset):
random_int = random.randrange(0, 1010)
form.instance.slug = slugify(form.instance.title) + str(random_int)
self.object = form.save()
form.instance.user.add(self.request.user)
formset.instance = self.object
formset.save()
return super(ShopCreateView, self).form_valid(form, formset)
class ShopUpdateView(LoginRequiredMixin, FormsetMixin, ShopMixin, UpdateView):
model = Shop
is_update_view = True
form_class = ShopForm
formset_class = ShopInlineFormSet
template_name = 'shop/shop_update.html'
mixin.py
class FormsetMixin(object):
object = None
def get(self, request, *args, **kwargs):
if getattr(self, 'is_update_view', False):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
formset_class = self.get_formset_class()
formset = self.get_formset(formset_class)
return self.render_to_response(self.get_context_data(form=form, formset=formset))
def post(self, request, *args, **kwargs):
if getattr(self, 'is_update_view', False):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
formset_class = self.get_formset_class()
formset = self.get_formset(formset_class)
if form.is_valid() and formset.is_valid():
return self.form_valid(form, formset)
else:
return self.form_invalid(form, formset)
def form_valid(self, form, formset):
self.object = form.save()
formset.instance = self.object
formset.save()
return redirect(self.object.get_absolute_url())
def get_formset_class(self):
return self.formset_class
def get_formset(self, formset_class):
return formset_class(**self.get_formset_kwargs())
def get_formset_kwargs(self):
kwargs = {
'instance': self.object
}
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
def form_invalid(self, form, formset):
return self.render_to_response(self.get_context_data(form=form, formset=formset))
sorry i cant fix in editor my mixin, but functions in mixin is in class.
So where i need to use conditon to do extra=0, when i have more than 1 contact to shop. but when i will press button add more it will be add one more form of contact. this is create page - create view
this is my update page - update view
so when i update shop settings i don't want to show second formset if it empty, just when i will click to first button at the bottom.
回答1:
The answer is was simple, i should use max_num=1
in
ShopInlineFormSet = inlineformset_factory(Shop, Contacts, extra=1,max_num=1,
fields=(
'published', 'phone', 'address', 'place', 'latitude',
'longitude', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday',
'saturday', 'sunday'), can_delete=True)
来源:https://stackoverflow.com/questions/45278491/inline-formset-factory-update-view