Why is my django core.serializers so slow - python

I have my a serializer from core.serializers in my django view. It does work, but it sometimes takes over 1 minute to show my results table. Any ideas how to get it faster?
# views.py
from django.core import serializers
def search_institution(request):
form = SearchInstitutionsForm()
qs = Institution.objects.all()
if request.method == "POST":
form = SearchInstitutionsForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
if cd['name']:
qs = Institution.objects.filter(name__contains=cd['name'])
print(f"Before requesting from db: {datetime.now()}")
print(f"After requesting from db, before serializing: {datetime.now()}")
context = {
"result_data": SafeString(serializers.serialize("json", qs)),
'form': form
}
print(f"After serializing, before rendering: {datetime.now()}")
return render(request, "landing/result_table.html", context)
else:
context = {
"form": SearchInstitutionsForm
}
return render(request, "stakeholders/institution_form.html", context)

Your print statements don't help much because Querysets are lazy. It means they are not evaluated at time of filtering qs = Institution.objects.filter(name__contains=cd['name']) but rather when the actual value is used.
So I'm not going much into serialization there are really nice ways of doing that, and Django on it's own provides good tools already.
Look into Queryset and database performance, it's the most essential topic, where I suspect your performance issue comes from. Also do more research on select_related and prefetch_related, it will help you reduce 200+ queries to 2
You can use django Debug toolbar in your local environment to easily monitor your application. But there are other profiling tools and tips too.

Related

How to follow the DRY principle in django when each view needs to deal with a different model?

I tried to choose a good
I have several pages with one form each. I have had to create a view for each of these pages (about 20 different pages), but the code is almost similiar. I don't see any way to cut down on repeating code on this as the different views all have to deal with a different ModelForm instance.
Example could would be for one view:
def portfolio_dividend_new(request, profile_id):
profile = Profile.objects.get(id=profile_id)
post_req = False
if request.POST:
form = DividendForm(request.POST)
form.save()
post_req = True
form = DividendForm()
return render(request, 'plan/portfolio/new_dividend.html',
{'form': form,
'profile': profile,
'post_req': post_req}
)
Example of another view:
def portfolio_buyback_new(request, profile_id):
profile = Profile.objects.get(id=profile_id)
post_req = False
if request.POST:
form = SharebuybackForm(request.POST)
form.save()
post_req = True
form = SharebuybackForm()
return render(request, 'plan/portfolio/new_buyback.html',
{'form': form,
'profile': profile,
'post_req': post_req}
)
As you can see these views have much of the same code but since they have to instantiate different ModelForm instances I dont see how to keep them from becoming two views. This wouldnt be a problem if it only were two views but its becoming like 20 views which is not maintainable anymore.
How can I avoid violating the DRY principle when I have to work with different modelforms in each view ? I dont see CBV as any better solution here as the code itself isnt very long at all and its simple enough, but the problem is that much of the code repeats itself.
Any suggestions ?
Make the differences parameters and use functools.partial to partially apply them.
from functools import partial
def portfolio_page(model, the_url, request, profile_id):
profile = Profile.objects.get(id=profile_id)
post_req = False
if request.POST:
form = model(request.POST)
form.save()
post_req = True
form = model()
return render(request, the_url,
{'form': form,
'profile': profile,
'post_req': post_req}
)
portfolio_dividend_new = partial(
portfolio_page, DividendForm, 'plan/portfolio/new_dividend.html')
portfolio_buyback_new = partial(
portfolio_page, SharebuybackForm, 'plan/portfolio/new_buyback.html')
Or something like that. You only gave two examples. You could possibly pull out even more similarities, like the 'plan/portfolio/{}.html'.format(the_file) if they're all the same. Or it might take more parameters if they differ in more places.
You can even partial your partial if you use it a lot, like
page = partial(partial, portfolio_page)
portfolio_dividend_new = page(DividendForm, 'new_dividend')
portfolio_buyback_new = page(SharebuybackForm, 'new_buyback')
foopage = page(FooModel, 'foo')
barpage = page(BarModel, 'bar')
# etc.
I did not know you could use the "model" in that statement as a variable.
Classes are just another type of object in Python (as are functions), so you can assign them to variables and pass them as parameters to other functions, etc.

How can i save a data on database using django views?

I tried saving data on database using django views but it return a error.
def get_enroll(request, pk):
user = request.user
users = User.objects.filter(username=user)
course = Course.objects.filter(pk=pk)
chapter = ChapterModel.objects.filter(course = course)
abc = Enroll()
abc.save_enroll(users, course, chapter)
template_name = 'dashboard.html'
context = {'users':user,'course':course}
return render(request, template_name, context)
You can save it directly like:
Enroll(user=user, course=course, chapter=chapter).save()
You can simply use:
abc = Enroll.objects.create(users=users, course=course, chapter=chapter)
Since you havent provided your models, nor any logic of how you want this to work, I cannot give you a better solution than this one.
Hope this helps

Django Row Level Locking For Model Forms

I am using Python 3.5, Django 1.8 and PostgreSql 9.4.
So I have one edit method where in get request I am rendering form and when user submit form it will get updated. Hers's the code
def edit_case(request, case_id):
case = get_object_or_404(Case, pk=case_id)
if request.method == 'POST':
data = request.POST.copy()
form = CaseEditForm(data, instance=case)
if form.is_valid():
res = form.save()
return HttpResponseRedirect(reverse("case_list"))
else:
form = CaseEditForm(instance=case)
variables = RequestContext(request, {
"form": form,
})
return render_to_response(
'sample/edit_case.html',
variables,
)
Now I want to add row level locking on it like if one user is updating something at the same time other will not be able update anything unless previous transaction succeeded Or if someone have any other better suggestions rather then using Pessimistic Locking.
I know about select_for_update but don't have any idea how it will get implemented in case of form.save()
Any help would be really appreciated
After so much research I have figured out the solution. So now while getting queryset against id I am using "select_for_update", something like this
with transaction.atomic():
case = get_object_or_404(Case.objects.select_for_update(), pk=case_id)
form = CaseEditForm(data, instance=case)
if form.is_valid():
res = form.save()
return HttpResponseRedirect(reverse("case_list"))
So as you can see now I am fetching the query set object under the transaction and if any exception appear during transaction it will automatically rollback and Also as I am using select_for_update so it will lock the row until the transaction get succeeded or failed.
If anyone have better suggestion then kindly share it.

How do I prevent repeat code for handling forms in views.py using decorators?

Context
I'm handling a form in a python view. Basic stuff.
def index(request):
# Handle form.
if request.method == 'POST':
form = CustomForm(request.POST)
if form.is_valid():
# Do stuff
return HttpResponseRedirect('/thankyou/')
else:
form = CustomForm()
# Render.
context = RequestContext(request, {
'form':form,
})
return render_to_response('app/index.html', context)
This form is shown on multiple pages, and I've ended up having duplicates of the form-handling code in multiple functions in views.py, rendering different templates. (However, the template code for the form resides in the base template)
That's dumb, so I tried looking around for ways to prevent the repeat of code. I like the suggested use of python decorators in this Stackoverflow question. I also found an excellent explanation of python's decorators here.
Question
I'm having trouble with trying to write the decorator. I need to return a form after the first if statement, followed by executing another if statement. But in a python function, no code after a return function gets executed... Does this require something like a nested decorator..?
Suggestions? Non-decorator suggestions welcome.
This is not the answer to your main question but this info may be helpful to you or somebody.
The question with suggestion about decorators is pretty old. Started from 1.3 version django have class based views - i think this is what you are looking for. By subclassing views you can reduce duplication of code (code from django docs just for example):
# Base view
class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/')
return render(request, self.template_name, {'form': form})
Now you can create another views classes based on MyFormView view. Form processing code stays same, but you can change it of course:
class AnotherView(MyFormView):
form_class = AnotherForm
initial = {'key1': 'value1'}
template_name = 'form1_template.html'
# you dont need to redefine post here if code stays same,
# post from base class will be used

django-mptt: dealing with concurrent inserts

I have a threaded comment system which works fine 99.9% of the time, but very occasionally the tree breaks down and left/right values get duplicated.
I have discovered that this happens when two posts happen at the same time (within a second of each other), and presumably what is happening is that the second post is updating the left/right values of the tree before the first has completed doing so.
My comment insert code from views.py is the following:
#login_required
#transaction.autocommit
def comment(request, post_id):
parent = get_object_or_404(Post, pk=post_id)
if request.method == 'POST':
form = PostForm(request.POST)
form.parent = post_id
if form.is_valid():
new_post = newPost(request.user, form.cleaned_data['subject'], form.cleaned_data['body'])
new_post.insert_at(parent, 'last-child', save=True)
return HttpResponseRedirect('/posts/')
else:
form = PostForm()
return render_to_response('posts/reply.html', {'requestPost': request.POST, 'form': form, 'parent': parent}, context_instance=RequestContext(request))
What is the correct approach to dealing with this? Is there a django way to ensure that the second view does not get called until the first database transaction is complete? Or should I rebuild the tree after each insert to ensure integrity? Or is there a better insert method to be using?
Thanks!
edit: I'm using MySQL.
transaction.autocommit() is a standard django behavior. You decorator does nothing, if global transaction behavior was not redefined.
Use should use commit_on_success() decorator. All db operations in view will be in one transaction.
You can read more on https://docs.djangoproject.com/en/1.5/topics/db/transactions/
PS: In django 1.6 transaction management will be updated, be attentive.

Categories

Resources