Django:ModelForm不提交

时间:2018-12-12 18:55:53

标签: django

我有两个步骤的表格。实际上,这是2种形式。第一个让我从渲染的size捕获quantityChoiceFields变量,并将它们保存在session中。

第二表单:呈现FileFieldCharField;并且在提交时应该检索存储在size中的quantitysession

因此,最后我要提交一个具有5个字段的SizeQuantity模型的记录:product(产品模型的外键),sizequantityimage(使其为可选-null True / blank为True以丢弃其引起的任何麻烦),comment(可选)。

但是,当我单击表单提交按钮时,在StepTwoForm(第二个表单和最终表单)上,我的表单未提交-因此未在DB中保存记录,我看不到管理员输入的任何内容(已注册型号)。

页面仅停留在该页面上,如果图像已上传,则该字段在html中变为空。

models.py

class Category(models.Model):
    name = models.CharField(max_length=250, unique=True)
    slug = models.SlugField(max_length=250, unique=True)
    description = models.TextField(blank=True)
    image = models.ImageField(upload_to='category', blank=True)

    class Meta:
        ordering = ('name',)
        verbose_name = 'category'
        verbose_name_plural = 'categories'

    def get_url(self):
        return reverse('shop:products_by_category', args=[self.slug])

    def __str__(self):
        return '{}'.format(self.name)


class Product(models.Model):
    name = models.CharField(max_length=250, unique=True)
    slug = models.SlugField(max_length=250, unique=True)
    description = models.TextField(blank=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    image = models.ImageField(upload_to='product', blank=True)
    stock = models.IntegerField()
    available = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('name',)
        verbose_name = 'product'
        verbose_name_plural = 'products'

    def get_url(self):
        return reverse('shop:ProdCatDetail', args=[self.category.slug, self.slug])

    def __str__(self):
        return '{}'.format(self.name)


class SizeQuantity(models.Model):

    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    size = models.CharField(max_length=10, choices=TAMANIOS)
    quantity = models.CharField(max_length=10, choices=CANTIDADES)
    image = models.ImageField(upload_to='images', blank=True, null=True)
    # imagenes = models.ImageField(upload_to='category', blank=True)
    comment = models.CharField(max_length=200, blank=True, null=True, default='')
    uploaded_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.size

views.py

# Tamanos y cantidades

class StepOneView(FormView):
    form_class = StepOneForm
    template_name = 'shop/product.html'
    success_url = 'shop/subir-arte'

    def get_initials(self):
         # pre-populate form if someone goes back and forth between forms
         initial = super(StepOneView, self).get_initial()
         initial['size'] = self.request.session.get('size', None)
         initial['quantity'] = self.request.session.get('quantity', None)
         initial['product'] = Product.objects.get(
                category__slug=self.kwargs['c_slug'],
                slug=self.kwargs['product_slug']
            )
         return initial

         # pre-populate form if someone goes back and forth between forms

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['product'] = Product.objects.get(
            category__slug=self.kwargs['c_slug'],
            slug=self.kwargs['product_slug']
        )
        return context


    def form_valid(self, form):
        # In form_valid method we can access the form data in dict format
        # and will store it in django session
        self.request.session['product'] = form.cleaned_data.get('product')
        self.request.session['size'] = form.cleaned_data.get('size')
        self.request.session['quantity'] = form.cleaned_data.get('quantity')
        return HttpResponseRedirect(self.get_success_url())


# here we are going to use CreateView to save the Third step ModelForm
class StepTwoView(CreateView):
    form_class = StepTwoForm
    template_name = 'shop/subir-arte.html'
    success_url = '/'


    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['product'] = Product.objects.get(
            category__slug=self.kwargs['c_slug'],
            slug=self.kwargs['product_slug']
        )
        return context

    def form_valid(self, form):
        # form.instance.product = Product.objects.get(
        #     category__slug=self.kwargs['c_slug'],
        #     slug=self.kwargs['product_slug']
        # )
        form.instance.product = self.request.session.get('product')  # get tamanios from session
        form.instance.size = self.request.session.get('size')  # get tamanios from session
        form.instance.quantity = self.request.session.get('quantity')  # get cantidades from session
        del self.request.session['product']
        del self.request.session['quantity']  # delete cantidades value from session
        del self.request.session['size']  # delete tamanios value from session
        self.request.session.modified = True
        return super(StepTwoView, self).form_valid(form)

forms.py:

class StepOneForm(forms.Form):
    size = forms.ChoiceField(choices=TAMANIOS, widget=forms.RadioSelect(), label='Selecciona un tamaño')
    quantity = forms.ChoiceField(choices=CANTIDADES, widget=forms.RadioSelect(), label='Selecciona la cantidad')


class StepTwoForm(forms.ModelForm):
    instructions = forms.CharField(widget=forms.Textarea)

    class Meta:
        model = SizeQuantity
        fields = ('image', 'comment')

    def __init__(self, *args, **kwargs):
        super(StepTwoForm, self).__init__(*args, **kwargs)
        self.fields['comment'].required = False
        self.fields['image'].required = False

    def save(self, commit=True):
        instance = super(StepTwoForm, self).save(commit=commit)
        # self.send_email()
        return instance

urls.py

urlpatterns = [

    path('', views.allProdCat, name = 'allProdCat'),
    path('<slug:c_slug>', views.allProdCat, name = 'products_by_category'),
    path('<slug:c_slug>/<slug:product_slug>/medida-y-cantidad', views.StepOneView.as_view(), name='ProdCatDetail'),
    path('<slug:c_slug>/<slug:product_slug>/subir-arte', views.StepTwoView.as_view(), name='UploadArt'),

]

subir-arte.html

<form method="post" enctype="multipart/form-data">
 {% csrf_token %}

 <div class="form-group">

   {{ form.image|as_crispy_field }}

 <div id="instrucciones-adicionales"  style="display: none">

 <p class="bold-font"> Instrucciones adicionales (opcional):</p>

 {{ form.comment|as_crispy_field }}

  </div>
</div>


</br>
</br>

<p>O, sáltate este paso y envía tu arte por correo electrónico</p>


<button type="submit" class="btn btn-naranja text-white btn-block">Continuar
</button>

</form>

项目设置文件

"""
Django settings for perfectcushion project.

Generated by 'django-admin startproject' using Django 2.1.3.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""

import os



# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '^_67&#r+(c+%pu&n+a%&dmxql^i^_$0f69)mnhf@)zq-rbxe9z'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'shop',
    'search_app',
    'cart',
    'stripe',
    'order',
    'crispy_forms',

]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'perfectcushion.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates'),
                 os.path.join(BASE_DIR, 'shop', 'templates/'),
                 os.path.join(BASE_DIR, 'search_app', 'templates/'),
                 os.path.join(BASE_DIR, 'cart', 'templates/'),
                 os.path.join(BASE_DIR, 'order', 'templates/'),]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'shop.context_processor.menu_links',
                'cart.context_processor.counter'
            ],
        },
    },
]

WSGI_APPLICATION = 'perfectcushion.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)


MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'static', 'media')


### Stripe Settings ###



CRISPY_TEMPLATE_PACK = 'bootstrap4'

1 个答案:

答案 0 :(得分:0)

在您的get_initials函数中,

 def get_initials(self):
     # pre-populate form if someone goes back and forth between forms
     initial = super(StepOneView, self).get_initials() #mispelled

您在超级菜单中拼写了错误的函数调用