Django - How To Remove Cached Results From Previous Form Posts?
I've got a django Form which contains a dictionary of strings. I've given the form a submit button and a preview button. When the preview button is pressed after entering some information, a POST is sent, and the strings in the dictionary are automagically recovered (I assume that it's done using session state or something). This is great, exactly what I wanted.
The problem is that if I don't submit the form, then do a GET (i.e. browse to the page with the form on it), enter some info and hit preview, the information that was stored in the dictionary from the first preview is still there.
How do you clear this information?
The following is my form:
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
And here is the view:
@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))
I haven't been programming with django or python all that long, so any pointers on fixing up some of the code is welcome :)
Answer
This code is broken in concept; it will never do what you want it to. Your dictionaries are class attributes on the ListingImagesForm class. This class is a module-level global. So you're storing some state in a global variable in-memory in a webserver process. This state is global to all users of your application, not just the user who submitted the form, and will persist (the same for all users) until it's explicitly changed or cleared (or until you just happen to have your next request served by a different process/thread in a production webserver).
[EDIT: I used "global" here in an unclear way. Class attributes aren't "global", they are encapsulated in the class namespace just as you'd expect. But you're assigning attributes to the class object, not to instances of the class (which you'd do within an __init__() method). The class object is a module-level global, and it only has one set of attributes. Every time you change them, you're changing them for everyone. If you'd modify the above code so that your three dictionaries are initialized within the __init__() method, then your "cached data" "problem" would go away; but so would the "magical" persistence behavior that you wanted in the first place.]
You need to rethink your design with a clear understanding that Django doesn't "automagically" maintain any state for you across requests. All your state must be explicitly passed via POST or GET, or explicitly saved to a session. Class attributes on a Form class should be avoided except for immutable configuration-type information, and instance attributes are only useful for keeping track of temporary state while processing a single request, they won't persist across requests (a new instance of your Form class is created on each request).
Related Questions
- → What are the pluses/minuses of different ways to configure GPIOs on the Beaglebone Black?
- → Django, code inside <script> tag doesn't work in a template
- → React - Django webpack config with dynamic 'output'
- → GAE Python app - Does URL matter for SEO?
- → Put a Rendered Django Template in Json along with some other items
- → session disappears when request is sent from fetch
- → Python Shopify API output formatted datetime string in django template
- → Can't turn off Javascript using Selenium
- → WebDriver click() vs JavaScript click()
- → Shopify app: adding a new shipping address via webhook
- → Shopify + Python library: how to create new shipping address
- → shopify python api: how do add new assets to published theme?
- → Access 'HTTP_X_SHOPIFY_SHOP_API_CALL_LIMIT' with Python Shopify Module