ZeroDivisionError on GET parameter django - django

middleware.py
def get_perpage(self):
try:
self.session['perpage'] = int(self.REQUEST['perpage'])
return self.session['perpage']
except (KeyError, ValueError, TypeError):
pass
try:
return int(self.session['perpage'])
except (KeyError, ValueError, TypeError):
return DEFAULT_PAGINATION
I have a problem: when i want to turn zero into URL as GET parameter (?perpage=0), it shows me ZeroDivisionError float division by zero. I need to take ALL objects on page without pagination when perpage=0. How can I do this? What is must be in view.py?

def render(self, context):
key = self.queryset_var.var
value = self.queryset_var.resolve(context)
if (self.paginate_by == None):
paginate_by = int(context['request'].perpage)
else:
paginate_by = self.paginate_by.resolve(context)
if (paginate_by == 0): #HERE
context['page_obj'] = value # IS
return u'' #SOLUTION
print (paginate_by)
paginator = Paginator(value, paginate_by, self.orphans)
try:
page_obj = paginator.page(context['request'].page)
except InvalidPage:
if INVALID_PAGE_RAISES_404:
raise Http404('Invalid page requested. If DEBUG were set to ' +
'False, an HTTP 404 page would have been shown instead.')
context[key] = []
context['invalid_page'] = True
return u''
if self.context_var is not None:
context[self.context_var] = page_obj.object_list
else:
context[key] = page_obj.object_list
context['paginator'] = paginator
context['page_obj'] = page_obj
return u''
when my view gets perpage=0, it returns pure object list (value) without Pagination to template

Related

Django - when 1 user accesses the same view with different url kwargs - why am I getting cross over of data?

I have a django app that contains samples. On my home page, it displays a table with many samples, containing hyperlinks to the 'Sample page' - which is a view get request.
When I click on several of these samples in tandem, to open new tabs, each to a specific tab - I am getting cross over of data - I.e the url sample_id kwargs is different, but the page is displaying the same results which is incorrect. When i refresh the page, the correct sample data appears.
Is there any way around this happening is a user is to open several different sample tabs at the same time? This would impact on results and could cause errors in the workflow offered by the django app.
*is this because my view is processing too much, so the different view request=s ends up over lapping ?
Edit: adding view:
class FilterVariantSampleView(ReportView, ReportPDFGenerator, FileGenerator, limsQuery):
template_name = os.path.join(
'results',
'filter_templates',
'sample_page.html'
)
type = 'sample'
choice = False
group_required = ['filter']
def get(self, request, *args, **kwargs):
self.user = request.user
self.obtain_sample_information(kwargs)
self.obtain_patient_information()
self.obtain_header()
# create sample notes form
sample_notes_form = SampleNotesForm(
instance=self.sample_obj)
self.context['sample_notes_form'] = sample_notes_form
self.create_variant_filter_formset()
panel_list = [o.run_id.machine_panel_id.panel_id
for o in self.all_sr_obj]
if len(panel_list):
self.panel_obj = panel_list[0]
# self.generate_hotspot_form()
self.assess_fails()
crs_qs = ClinicallyReportedSample.objects.filter(
sample_id=self.sample_obj)
crs_qs = crs_qs.exclude(
reported_on_panel__parent_panel__isnull=False,
primary_technical_report=False,
final_technical_report=False
)
remove_report_form_list = []
lims_molecular_results = self.query_lims_clone_molecular(
qs=crs_qs)
mol_df = lims_molecular_results[0]
summary = lims_molecular_results[1]
self.context['summary'] = summary
if crs_qs.count() == 1:
crs_obj = crs_qs[0]
self.context['crs_qs'] = crs_qs
remove_report_form = RemoveDiagnosticReportForm(
instance=crs_obj)
remove_report_form_list.append(remove_report_form)
else:
messages.add_message(self.request, messages.WARNING,
'This sample has been sequenced on multiple panels.')
self.context['crs_qs'] = crs_qs
lims_molecular_results = self.query_molecular_lims(
sample_obj=self.sample_obj)
for crs_obj in crs_qs:
remove_report_form = RemoveDiagnosticReportForm(
instance=crs_obj)
remove_report_form_list.append(remove_report_form)
if crs_obj.diagnostic_report_required == False:
messages.add_message(self.request, messages.WARNING,
f'This sample does NOT require a diagnostic reoprt '
f'for the {crs_obj.reported_on_panel} panel.')
self.context['remove_report_form_list'] = remove_report_form_list
return render(request, self.template_name, self.context)
def post(self, request, *args, **kwargs):
"""
"""
self.define_variant_filter_formset()
submit = request.POST.get('submit', None)
if submit:
if submit == 'Modify sample':
logger.info('')
logger.info('Sample: {}'.format(self.sample_obj))
logger.info("Submit: '{}'".format(submit))
# pass POST dict to formset
modify_formset = self.CRVFormSet(request.POST, prefix='crv')
# validate
if modify_formset.is_valid():
logger.info('Modify Variant Formset valid')
logger.info('')
self.modify_variants(modify_formset)
self.modify_sample()
return HttpResponseRedirect(
reverse('results:filter_variant_sample',
kwargs={'sample_id': self.sample_obj.id}))
else:
msg = ('Modify ClinicallyReportedVariant '
f'Formset NOT valid: {modify_formset.errors}')
logger.error(msg)
messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(
reverse('results:filter_variant_sample',
kwargs={'sample_id': self.sample_obj.id}))
elif submit == 'Update':
form = RemoveDiagnosticReportForm(request.POST,
instance=ClinicallyReportedSample.objects.get(
sample_id=kwargs['sample_id'],
reported_on_panel=request.POST['reported_on_panel'])
)
if form.is_valid():
logger.info('RemoveDiagnosticReportForm is valid')
try:
form.save()
except Exception as e:
logger.error(e)
else:
msg = f'RemoveDiagnosticReportForm is NOT valid: {form.errors}'
logger.error(msg)
messages.add_message(self.request, messages.ERROR, msg)
return HttpResponseRedirect(request.path_info)
elif 'Download' in submit:
panel_name = submit.split(' ')[1]
self.panel_obj = Panel.objects.get(panel_name=panel_name)
self.crs_obj = ClinicallyReportedSample.objects.get(
sample_id=self.sample_obj, reported_on_panel=self.panel_obj)
if 'panel data' in submit:
logger.info(f'Downloading data for {self.sample_obj}')
if self.crs_obj.sample_id.external_dept.site in ['Newcastle', 'Sheffield']:
downloaded_data = self.download_yne_data()
if downloaded_data:
self.crs_obj.downloaded_data = True
self.crs_obj.downloaded_data_user = request.user
self.crs_obj.downloaded_data_date = timezone.now()
self.crs_obj.save()
return downloaded_data
else:
return HttpResponseRedirect(self.request.path_info)
elif 'report' in submit:
logger.info(f'Downloading report for {self.sample_obj}')
# update crs_obj
self.crs_obj.download_technical_report = True
self.crs_obj.download_technical_report_user = self.user
self.crs_obj.download_technical_report_date = timezone.now()
self.crs_obj.save()
# return HttpResponseRedirect(self.request.path_info)
lims_molecular_results = self.query_molecular_lims(
sample_obj=self.sample_obj)
mol_df = lims_molecular_results[0]
summary = lims_molecular_results[1]
if mol_df.empty:
logger.info('No molecular tests done')
self.latex_context['gene_status'] = False
else:
gene = mol_df[
(mol_df['test_name'] == 'gene') &
(mol_df['status'] == 'complete')
]
if gene.empty:
self.context['gene'] = False
else:
msg = ("gene Sanger in-fill test has been completed.{}")
result = gene['result'].to_string(index=False)
if result == 'normal or wild-type':
msg = msg.format(' No detectable variants.')
msg_info = messages.INFO
gene_df = pd.DataFrame()
elif result == 'failed':
msg = msg.format(' Unfortunately the test failed.')
msg_info = messages.WARNING
gene_df = pd.DataFrame()
elif result == 'mutated' or result == 'suspicious':
gene_df = self.get_gene_result(gene, technical_report=True)
if result == 'suspicious':
msg = msg.format(' There is suspicion of a variant '
'(see below for more information).')
else:
msg = msg.format(' A variant was detected '
'(see below for more information).')
msg_info = messages.INFO
else:
msg = msg.format(' Error - contact administrator.')
msg_info = messages.ERROR
result = 'error'
gene_df = pd.DataFrame()
self.latex_context['gene_status'] = result
self.latex_context['gene_df'] = gene_df
logger.info(msg)
messages.add_message(self.request, msg_info, msg)
print(self.latex_context)
# call method from TechnicalReportPDFGenerator
self.generateReport(report_type='technical')
response = self.download_technical_report()
return response
return render(request, self.template_name, self.context)
This may be due to the cache of your browser, are you sure the calls are going through the first time ?

How to increment inside session in Django?

I try to create a counter inside session but I fail. the session is print out the result I added once and it doesn't increment the process when I want to add a new comment again. the comment will be added but counter is still equal to one so, how can I do increment into session:
def post(self, request, user_slug, *args, **kwargs):
my_question = UserAsking.objects.get(ask_slug=user_slug)
userprof = UserProfile.objects.get(userasking__ask_slug=user_slug)
comment_form = CommentForm(request.POST, instance=request.user)
name = "%s %s" % (self.request.user.first_name, self.request.user.last_name)
username = self.request.user.username
logo = self.request.user.userprofile.logo.url
if comment_form.is_valid():
comment_request = self.request.POST.get('comment', None)
comment_form = Comment.objects.create(comment=comment_request,
userasking_id=my_question.id,
userprofile_id=userprof.id,
name=name,
username=username,
logo=logo,
comment_slug=my_question.ask_slug
)
q = UserAsking.objects.get(ask_slug=my_question.ask_slug)
c = comment_form
u = comment_form.userprofile
if 'notify_counts' in request.session:
counter = request.session.get('notify_counts', 0)
request.session['notify_counts'] = counter + 1
request.session.save()
print('%s is commented your post: %s and comment is (%s) notify = %i'
%(u, q, c, counter))
return redirect('community:question_view', user_slug)
# return redirect('community:question_view', comment_form.userasking.ask_slug)
return render(request, 'community/question_view.html', {'comment_form': comment_form})
Django automatically saves to the session database when the session has been modified, so you won't bother to save it manually, take a look:when session are stored[Django-Doc].
def post(request,...):
...
notify_counts = request.session.get('notify_counts')
if notify_counts is None:
request.session['notify_counts'] = 1
else:
request.session['notify_counts'] +=1
Also you could use try...except pattern as follows:
def post(request, ...):
try:
request.session['notify_counts'] +=1
except KeyError:
request.session['notify_counts'] = 1

How can I convert the following Django view to return JSON with Django Rest Framework?

I am returning a bunch of tuples with the following code. The returned values involves data from a number of different models. I was wondering how to serialize the data and eventually return it in JSON format.
def Stream(request):
questions = Question.objects.all()
answers = Answer.objects.filter(hearts__gte=1)
combined = sorted(chain(questions, answers), key=attrgetter('created'), reverse=True)
queryset = []
for item in combined:
if hasattr(item, 'parent'):
try:
qs_heart = AnswerHeart.objects.get(answer=item, user=request.user)
if qs_heart:
hearted = True
except AnswerHeart.DoesNotExist:
hearted = False
try:
qs_flag = AnswerFlag.objects.get(answer=item, user=request.user)
if qs_flag:
flagged = True
except AnswerFlag.DoesNotExist:
flagged = False
queryset.append((item, hearted, flagged))
else:
try:
qs_heart = QuestionHeart.objects.get(question=item, user=request.user)
if qs_heart:
hearted = True
except QuestionHeart.DoesNotExist:
hearted = False
try:
qs_flag = QuestionFlag.objects.get(question=item, user=request.user)
if qs_flag:
flagged = True
except QuestionFlag.DoesNotExist:
flagged = False
queryset.append((item, hearted, flagged))
comments = QuestionComment.objects.all()
return render(request, "alpha/stream.html", {'queryset': queryset, 'comments': comments})
Can't you just do something like this?
class MyThingSerializer(serializers.Serializer):
my_thing_email = serializers.EmailField()
def my_view(request):
serializer = MyThingSerializer(my_things, many=True)
return HttpResponse(JSONRenderer().render(serializer.data), content_type='application/json')

Django Rest Framework Paging

I am attempting to make my API get return a maximum of 10 per page. This helps me with infinite loading. The API url will be I am trying looks like this:
www.mysite.com/api/test/?user=5&page=1
However, this does not work.
I've followed the official docs here without success.
I have only modified two files, settings.py & rest_views.py.
settings.py-
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}
rest_views.py-
from django.core.paginator import Paginator
...
wardrobematch = {
'user': lambda x: ('user__pk', x)
}
class WardrobeListView(APIView):
renderer_classes = (JSONRenderer, )
paginate_by = 10
paginate_by_param = 'page_size'
max_paginate_by = 100
def get(self, request, *args, **kwargs):
filters = {}
for key, value in request.GET.items():
key = key.lower()
if key in wardrobematch:
lookup, val = wardrobematch[key](value.lower())
filters[lookup] = val
qset = (
Analytic.objects
.filter(like=True,**filters)
.order_by('-updated',)
# .distinct('product_id',)
.values('product_id', 'product__name', 'product__brand', 'product__store__store_name', 'product__variation__image__image', 'product__variation__price__price',)
)
return Response(qset)
When using regular ApiView, you should call the pagination API yourself, it will not perform pagination automatically.
I have created a pagination and a serializer mixim. I'm not sure it is best method, but it worked for me.
class SerializerMixim(object):
def serialize_object(self,obj):
"""Serilize only needed fields"""
return NotImplementedError
class PaginationMixim(object):
_serializer = None
def paginate(self,queryset,num=10):
page = self.request.GET.get('page')
paginator = Paginator(queryset, num)
try:
queryset = paginator.page(page)
except PageNotAnInteger:
queryset = paginator.page(1)
except EmptyPage:
queryset = paginator.page(paginator.num_pages)
count = paginator.count
previous = None if not queryset.has_previous() else queryset.previous_page_number()
next = None if not queryset.has_next() else queryset.next_page_number()
if self._serializer:
objects = self._serializer(queryset.object_list,many=True).data
else:
objects = [self.serialize_object(i) for i in queryset.object_list]
data = {'count':count,'previous':previous,
'next':next,'object_list':objects}
return Response(data)
def serialize_object(self,obj):
return {'id':obj.pk}
class WardrobeListView(APIView,PaginationMixim,SerializerMixim):
renderer_classes = (JSONRenderer, )
#_serializer = AnalyticSerializer
def get(self, request, *args, **kwargs):
filters = {}
for key, value in request.GET.items():
key = key.lower()
if key in wardrobematch:
lookup, val = wardrobematch[key](value.lower())
filters[lookup] = val
qset = (
Analytic.objects
.filter(like=True,**filters)
.order_by('-updated',)
# .distinct('product_id',)
return self.paginate(qset)
def serialize_object(self,obj):
return obj.serilized
then you need to create a propery for Analytic model like,
class Analytic(models.Model):
.....
#property
def serilized(self):
summary = {
'id':self.product.id,
'image':self.product.name,
.......
}
return summary
this will also work with django rest serializers
I got your first example working- to me it was clearer and more basic. All I did was add ".object_list" to stop the "is not JSON serializable" error.
This is your answer with my tiny tweak:
class WardrobeListView(APIView):
renderer_classes = (JSONRenderer, )
def get(self, request, *args, **kwargs):
filters = {}
for key, value in request.GET.items():
key = key.lower()
if key in wardrobematch:
lookup, val = wardrobematch[key](value.lower())
filters[lookup] = val
qset = (
Analytic.objects
.filter(like=True,**filters)
.order_by('-updated',)
# .distinct('product_id',)
.values('product_id', 'product__name', 'product__brand', 'product__store__store_name', 'product__variation__image__image', 'product__variation__price__price',)
)
paginator = Paginator(qset, 2) # Show 25 items per page
page = request.GET.get('page')
try:
qset = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
qset = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
qset = paginator.page(paginator.num_pages)
return Response(qset.object_list)

how to work with modelform and multiwidget

Newbie to all this! i'm working on displaying phone field displayed as (xxx)xxx-xxxx on front end.below is my code. My question is 1. all fields are mandatory, for some reason,phone is not behaving as expected.Even if it is left blank its not complaining and 2.how can i test this widget's functionality
class USPhoneNumberWidget(forms.MultiWidget):
def __init__(self,attrs=None):
widgets = (forms.TextInput(attrs={'size':'3','maxlength':'3'}),forms.TextInput(attrs={'size':'3','maxlength':'3'}),forms.TextInput(attrs={'size':'3','maxlength':'4'}))
super(USPhoneNumberWidget,self).__init__(widgets,attrs=attrs)
def decompress(self, value):
if value:
val = value.split('-')
return [val[0],val[1],val[2]]
return [None,None,None]
def compress(self, data_list):
if data_list[0] and data_list[1] and data_list[2]:
ph1 = self.check_value(data_list[0])
ph2 = self.check_value(data_list[1])
ph3 = self.check_value(data_list[2])
return '%s''%s''%s' %(ph1,ph2,ph3)
else:
return None
def check_value(self,val):
try:
if val.isdigit():
return val
except:
raise forms.ValidationError('This Field has to be a number!')
def clean(self, value):
try:
value = re.sub('(\(|\)|\s+)','',smart_unicode(value))
m = phone_digits_re.search(value)
if m:
return u'%s%s%s' % (m.group(1),m.group(2),m.group(3))
except:
raise ValidationError('Phone Number is required.')
def value_from_datadict(self,data,files,name):
val_list = [widget.value_from_datadict(data,files,name+'_%s' %i) for i,widget in enumerate(self.widgets)]
try:
return val_list
except ValueError:
return ''
def format_output(self,rendered_widgets):
return '('+rendered_widgets[0]+')'+rendered_widgets[1]+'-'+rendered_widgets[2]
class CustomerForm(ModelForm):
phone = forms.CharField(required=True,widget=USPhoneNumberWidget())
class Meta:
model = Customer
fields = ('fname','lname','address1','address2','city','state','zipcode','phone')
In models blank and null are not true.
Any input it highly appreciated.Thanks
Here is the phone field:
phone = forms.CharField(label = 'Phone',widget=USPhoneNumberWidget()
class USPhoneNumberWidget(forms.MultiWidget):
"""
A widget that splits phone number into areacode/next3/last4 with textinput.
"""
def __init__(self,attrs=None):
widgets = (forms.TextInput(attrs={'size':'3','maxlength':'3'}),forms.TextInput(attrs={'size':'3','maxlength':'3'}),forms.TextInput(attrs={'size':'4','maxlength':'4'}))
super(USPhoneNumberWidget,self).__init__(widgets,attrs=attrs)
def decompress(self, value):
if value:
val = value
return val[:3],val[3:6],val[6:]
return None,None,None
def compress(self, data_list):
if data_list[0] and data_list[1] and data_list[2]:
return '%s''%s''%s' %(data_list[0],data_list[1],data_list[2])
else:
return None
def value_from_datadict(self,data,files,name):
val_list = [widget.value_from_datadict(data,files,name+'_%s' %i) for i,widget in enumerate(self.widgets)]
if val_list:
return '%s''%s''%s' %(val_list[0],val_list[1],val_list[2])
def format_output(self,rendered_widgets):
return '( '+rendered_widgets[0]+' )'+rendered_widgets[1]+' - '+rendered_widgets[2]
But depending on how you store the phone# in db 'return' line is to be changed. here I'm accepting it as (xxx)-xxx-xxxx format.In compress it receives ph_0(areacode),ph_1(next 3),ph_2(last4) in that order.but I'm storing it as xxxxxxxxxx.
Firebug helped me understand better about what return values should be. I'll update the answer when i come to know how testing could be done.