Django .save() doesn't take effect - django

I would like to understand why I need to rerun the Django server in order to watch the effect of .save() method.
When I upload a new document, I use code that lets me see if the document is recent or not. For example, I set the expiration time to 15 seconds after the upload part (15 seconds is for testing purposes, it will be 1 week in production).
I have this class :
class DocumentListView(CreateView):
""" Render the home page """
template_name = 'documentList.html'
form_class = DocumentForm
def get_context_data(self, **kwargs):
now = timezone.now()
for document in Document.objects.all():
expiration_delay = document.creation_date + timedelta(seconds=15)
if now > expiration_delay:
document.new_document = False
document.save()
kwargs['document_list'] = Document.objects.all().order_by('publication__category__name')
return super(HomeView, self).get_context_data(**kwargs)
It works fine, but after 15 seconds, when I want to refresh my page, the flag is still there. It disappears only when I rerun my Django server.

Related

Django-filters resets after using the UpdateView

I have a Model with a lot of entries, so I'm using django-filters to filter the model, I initially load an empty table and from there I use the filter to view the items.
Everything works fine, the page loads initially with no entry, after I filter, django shows the correct items.
The Url gets a parameter: /retetabloc/?acordcadru=532(532 is the filter) but when I try to update an entry, the filter resets(the parameter is still in the URL) and the whole db is loaded.
I don't quite understand how to pass the filter parameter to the RetetaBlocUpdate, so that after the update is done it returns to the filtered items like in the ListView.
views.py
class RetetaBlocListview(LoginRequiredMixin, CoreListView):
model = RetetaBloc
def get_queryset(self, *args, **kwargs):
pdb.set_trace()
acordcadru = self.request.GET.get("acordcadru")
queryset = RetetaBloc.objects.filter(acordcadru=acordcadru)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = RetetaBlocFilter(self.request.GET, queryset=self.get_queryset())
pdb.set_trace()
return context
class RetetaBlocUpdate(LoginRequiredMixin, AjaxUpdateView):
model = RetetaBloc
form_class = RetetaBlocForm
Thank you.
If you'd like filters to be remembered you could add them to a session variable instead. That way filters would be recalled even if they didn't go back directly from the update page (and you'd wouldn't have redundant URL querystring on pages where they weren't needed).
Something like:
def get_queryset(self, *args, **kwargs):
pdb.set_trace()
#check for new filter in URL first
acordcadru = self.request.GET.get("acordcadru")
#if nothing check for session variable
if not acordcadru:
acordcadru = self.request.session.get('acordcadru')
#if something in URL querystring, set it in session variable
else:
self.request.session['acordcadru'] = acordcadru
queryset = RetetaBloc.objects.filter(acordcadru=acordcadru)
return queryset

How to securely get time delta between form load and form submit?

In Django, I have a view with the following method:
def get(request):
if request.method=='POST':
# ... Process a filled form
else:
# ... Render a blank form
Tracking the epoch delta between when a form is rendered and returned is crucial to my application. In prototyping, I just used a hidden field to store the epoch of the render, but this is not secure (users can still edit a hidden field).
def get(request):
if request.method=='POST':
# ... Process a filled form
render_epoch = request.session['render_epoch']
submit_epoch = time.time()
else:
# ... Render a blank form
request.session['render_epoch'] = time.time()
However, this solution updates the epoch when a user "backs" into a cached form.

Django form field initial strfrtime value not updating

I have a Django form field, for a time, where I set the initial value to the current time by using the time.strfrtime() function.
Using this method, the field is initially populated correctly with the current time when I first load the Django app (by executing python manage.py runserver). However, subsequently if I reload the page, the form field fails to update the current time, instead repeatedly spitting back the time the app was first started. However, if I modify one of my Django files, such as forms.py or views.py, then the current time is correctly refreshed.
In forms.py:
class EventForm(ModelForm):
end_time = forms.TimeField(label="Current time", initial=strftime("%I:%M %p"))
In views.py:
def index(request):
event_form = EventForm()
How do I get the end_time field's initial value to always update to the current time?
Note: I'm aware I can fix this by passing in initial data to my event_form = EventForm() code, such as:
event_form = EventForm(initial={'end_time':strftime("%I:%M %p")})
But is there a better way? What's going on behind the scenes that the current time won't update automatically itself?
You need to set it in __init__() method of the class.
from time import strftime
from django import forms
class EventForm(forms.Form):
end_time = forms.TimeField(label='Current time')
def __init__(self, *args, **kwargs):
kwargs.update(initial={
'end_time': strftime('%I:%M %p')
})
super(EventForm, self).__init__(*args, **kwargs)

Cache staleness, even though I am not using a cache

I have uploaded my Django site on a development server at Digital Ocean and started serving it using apache2 and mod_wsgi. I am also using apache2 to serve static content. It's a fresh installation of Debian on the server, and have done minimal changes.
I am using Django Haystack and Solr to support full-text search. I've checked that both the database and Solr are kept up to date.
Now, if the url I use to retrieve a page contains a query string (it can be as small a ?asd, where asd is not a valid param) everything comes out fine.
If however it does not contain such a query string, I get a version of the page that can be several hours (days?) old, even containing items I've deleted from the database.
The issue is resolved as soon as I restart apache2.
Doing apache2ctl -M | grep cache returns nothing, and settings.py does not reference caching either. Anyone have an idea what could be the cause of this?
Update: my view is a standard search view:
class SearchView(SearchView):
form_class = ArticleSearchForm
template_name = 'articles/index.html'
paginate_by = 5
def get_queryset(self):
queryset = super(SearchView, self).get_queryset()
return queryset
def get_context_data(self, *args, **kwargs):
context = super(SearchView, self).get_context_data(*args, **kwargs)
context['ctx'] = context
context['articles'] = map(lambda o: o.object, context['object_list'])
return context
And the associated search form:
class ArticleSearchForm(SearchForm):
start_date = forms.DateField(required=False, widget=forms.DateInput(attrs={ 'id': 'start_date', 'class': 'form-control' }))
end_date = forms.DateField(required=False, widget=forms.DateInput(attrs={ 'id': 'end_date', 'class': 'form-control'}))
def __init__(self, *args, **kwargs):
super(ArticleSearchForm, self).__init__(*args, **kwargs)
self.fields['q'].widget.attrs['class'] = 'form-control'
def search(self):
sqs = super(ArticleSearchForm, self).search()
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get('q'):
sqs = self.searchqueryset.all()
if self.cleaned_data['start_date']:
sqs = sqs.filter(pub_date__gte=self.cleaned_data['start_date'])
if self.cleaned_data['end_date']:
sqs = sqs.filter(pub_date__lte=self.cleaned_data['end_date']+datetime.timedelta(days=1))
return sqs
But considering the page I get is inconsistent with what's in the database, I don't think my code gets called at all.
Update 2: It's weirder than this. Sometimes upon hitting refresh on my browser I get correct results. Hitting refresh again a couple of times I get incorrect results again. I tried wgetting the page on the server (via localhost) and I get incorrect results.

Django forms class that does not refresh

I have noticed a weird behavior in one of my Django applications, running with apache/mod_wsgi. There is a screen that displays a form, basically a dropown list with a list of availability to schedule a given site, computed from the difference between a given weekly capacity (3 sites/wk) and the total number of sites already scheduled at a given week.
This form (ScheduleForm) is rendered from following view (followup/views.py):
def schedule(request, site_id):
site = Site.objects.get(pk=site_id)
if request.method == 'POST':
form = ScheduleForm(request.POST)
if form.is_valid():
(year, week) = request.POST['available_slots'].split('/')
site.scheduled = week2date(int(year), int(week[1:]))
site.save()
return HttpResponseRedirect('/stats/')
else:
form = ScheduleForm()
return render_to_response('followup/schedule_form.html',{
'form': form,
'site': site
}, context_instance=RequestContext(request))
Here is the form class (followup/forms.py):
class ScheduleForm(forms.Form):
"""
Temporary lists
"""
schedules = Site.objects.filter(
scheduled__isnull=False
).values('scheduled').annotate(Count('id')).order_by('scheduled')
integration = {}
available_integration = []
# This aggregates all schedules by distinct weeks
for schedule in schedules:
if schedule['scheduled'].strftime('%Y/W%W') in integration.keys():
integration[schedule['scheduled'].strftime('%Y/W%W')] += schedule['id__count']
else:
integration[schedule['scheduled'].strftime('%Y/W%W')] = schedule['id__count']
for w in range(12): # Calculates availability for the next 3 months (3months*4 weeks)
dt = (date.today() + timedelta(weeks=w)).strftime('%Y/W%W')
if dt in integration.keys():
capacity = 3-integration[dt]
else:
capacity = 3
if capacity>0:
available_integration.append([dt, capacity])
"""
Form
"""
available_slots = forms.ChoiceField(
[[slot[0], '%s (%s slots available)' % (slot[0], slot[1])] for slot in available_integration]
)
class IntegrateForm(forms.Form):
integrated_on = forms.DateField(widget=AdminDateWidget())
This actually works fine but the only problem is that the list of availability is not refreshed when a site is scheduled, unless I restart the apache process each time I schedule a site.
It's like if the availability list would be cached by the form class...
Any idea would be warmly welcomed. Thank you in advance for any kind of help.
This has to do with how python works and not django.
This code below
class ScheduleForm(forms.Form):
"""
Temporary lists
"""
schedules = Site.objects.filter(
scheduled__isnull=False
).values('scheduled').annotate(Count('id')).order_by('scheduled')
integration = {}
available_integration = []
will be evalutated only once - when the server starts.
You shouldn't do these things on the class level, but on the instance level.
Most likely inside the __init__ method of your form.
See the examples below:
Django - change min_length in form __init__?
django model form, restrict choices based on value in ForeignKey model
Django "dynamic" verification form (updated)
I have modified my code as follows and it's now working like a charm :) I provide it here in case it helps anyone with a similar problem.
class ScheduleForm(forms.Form):
available_slots = forms.ChoiceField()
def __init__(self, *args, **kwargs):
super(ScheduleForm, self).__init__(*args, **kwargs)
schedules = Site.objects.filter(
scheduled__isnull=False
).values('scheduled').annotate(Count('id')).order_by('scheduled')
integration = {}
available_integration = []
# This aggregates all schedules by distinct weeks
for schedule in schedules:
if schedule['scheduled'].strftime('%Y/W%W') in integration.keys():
integration[schedule['scheduled'].strftime('%Y/W%W')] += schedule['id__count']
else:
integration[schedule['scheduled'].strftime('%Y/W%W')] = schedule['id__count']
for w in range(12): # Calculates availability for the next 3 months (3months*4 weeks)
dt = (date.today() + timedelta(weeks=w)).strftime('%Y/W%W')
if dt in integration.keys():
capacity = 3-integration[dt]
else:
capacity = 3
if capacity>0:
available_integration.append([dt, capacity])
self.fields['available_slots'].choices = [[slot[0], '%s (%s slots available)' % (slot[0], slot[1])] for slot in available_integration]