我有一个包含字典字典的django表单。我给了表单一个提交按钮和一个预览按钮。在输入一些信息后按下预览按钮时,会发送一个POST,并自动恢复字典中的字符串(我假设它是使用会话状态或其他东西完成的)。这很棒,正是我想要的。
问题是,如果我不提交表单,那么执行GET(即浏览到包含表单的页面),输入一些信息并点击预览,存储在字典中的信息来自第一次预览仍在那里。
您如何清除此信息?
以下是我的表格:
class ListingImagesForm(forms.Form):
#the following should be indented
def clear_dictionaries(self):
self.statuses = {}
self.thumbnail_urls = {}
self.image_urls = {}
statuses = {}
thumbnail_urls = {}
image_urls = {}
valid_images = SortedDict() #from the django framework
photo_0 = forms.ImageField(required=False, label='First photo')
photo_1 = forms.ImageField(required=False, label='Second photo')
def clean_photo_0(self):
return self._clean_photo("photo_0")
def clean_photo_1(self):
return self._clean_photo("photo_1")
def _clean_photo(self, dataName):
data = self.cleaned_data[dataName]
if data != None:
if data.size > max_photo_size:
raise forms.ValidationError("The maximum image size allowed is 500KB")
elif data.size == 0:
raise forms.ValidationError("The image given is empty.")
else:
self.valid_images[dataName] = data
self.statuses[dataName] = True
list_of_image_locs = thumbs.save_image_and_thumbs(data.name, data)
self.image_urls[dataName] = list_of_image_locs[0]
self.thumbnail_urls[dataName] = list_of_image_locs[1]
return data
以下是观点:
@login_required
def add(request):
#the following should be indented
preview = False
added = False
new_listing = None
owner = None
if request.POST:
form = GeneralListingForm(request.POST)
image_form = ListingImagesForm(request.POST, request.FILES)
if image_form.is_valid() and form.is_valid():
new_listing = form.save(commit=False)
new_listing.owner = request.user.get_profile()
if request.POST.get('preview', False):
preview = True
owner = new_listing.owner
elif request.POST.get('submit', False):
new_listing.save()
for image in image_form.image_urls:
url = image_form.image_urls[image]
try:
new_image = Image.objects.get(photo=url)
new_image.listings.add(new_listing)
new_image.save()
except:
new_image = Image(photo=url)
new_image.save()
new_image.listings.add(new_listing)
new_image.save()
form = GeneralListingForm()
image_form = ListingImagesForm()
image_form.clear_dictionaries()
added = True
else:
form = GeneralListingForm()
image_form = ListingImagesForm()
image_form.clear_dictionaries()
return render_to_response('add_listing.html', {'form': form, 'image_form' : image_form,
'preview': preview, 'added': added,
'owner': owner, 'listing': new_listing,
'currentmaintab': 'listings',
'currentcategory': 'all'},
context_instance=RequestContext(request))
我没有用django或python编程那么久,所以欢迎修改一些代码的任何指针:)
答案 0 :(得分:2)
此代码在概念上被打破;它永远不会做你想要的。您的词典是ListingImagesForm类的类属性。此类是模块级全局。因此,您将一些状态存储在Web服务器进程的内存中的全局变量中。此状态对于您的应用程序的所有用户而言都是全局的,而不仅仅是提交表单的用户,并且将一直保持(对所有用户都相同),直到明确更改或清除(或直到您恰好让您的下一个请求由生产网络服务器中的不同进程/线程。)
[编辑:我在这里以不明确的方式使用“全球”。类属性不是“全局”的,它们就像你期望的那样封装在类命名空间中。但是您要将属性分配给类对象,而不是类的实例(您在__init __()方法中执行)。类对象是模块级全局,它只有一组属性。每次你改变它们,你都会为每个人改变它们。如果你修改上面的代码,以便在__init __()方法中初始化你的三个词典,那么你的“缓存数据”“问题”就会消失;但你首先想要的“神奇”持久行为也是如此。]
您需要重新考虑您的设计,并清楚地了解Django不会在请求中“自动”为您维护任何状态。您的所有状态必须通过POST或GET显式传递,或明确保存到会话中。除了不可变的配置类型信息之外,应该避免使用Form类的类属性,并且实例属性仅用于在处理单个请求时跟踪临时状态,它们不会跨请求持久化(Form类的新实例)是在每个请求上创建的。)