我有两个步骤的表格。实际上,这是2种形式。第一个让我从渲染的size
捕获quantity
和ChoiceFields
变量,并将它们保存在session
中。
第二表单:呈现FileField
和CharField
;并且在提交时应该检索存储在size
中的quantity
和session
。
因此,最后我要提交一个具有5个字段的SizeQuantity模型的记录:product
(产品模型的外键),size
,quantity
,image
(使其为可选-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'
答案 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
您在超级菜单中拼写了错误的函数调用