内联formset工厂更新视图

时间:2017-07-24 10:42:26

标签: python django forms django-forms formsets

我希望在更新视图extra=0中进入内联formset工厂,如果它有多个联系人。所以这是我的代码

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))
抱歉,我无法修改编辑器我的mixin,但是mixin中的函数在课堂上。

所以我需要使用conditon做额外= 0,当我有超过1个联系购物。但是当我按下按钮添加更多时,它将添加另一种形式的联系。 this is create page - create view

this is my update page - update view

所以当我更新商店设置时,我不想显示第二个formset如果它是空的,就在我点击底部的第一个按钮时。

1 个答案:

答案 0 :(得分:0)

答案很简单,我应该在

中使用max_num=1
 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)