Why does this Django form rendering taking forever? - python

I have a ModelForm based on a gigantic 300 fields model. Actually one model with 150 fields inheriting from another one with 150 other.
I was expecting the model to cause some issues at syncdb or save(), but it works fine.
However, calling the form based on this model as_p() method just take forever. I can wait 10 minutes without seen any output. Same for any HTML rendering method for this form. No error, just python hanging there wherever I'm in the shell or in the dev server.
Is there any known limitation or bug for hug forms in Django? Is there a workaround?
I'm suspecting some issue with string concatenation. I'm going to dig in the Django source code in the meantime, but if anybody got some clue that would save my day.

if you have foreign keys to tables with a large number of rows, it's worth remembering that the default widget for each is a dropdown (<select>) with each row ('s unicode) as a choice. these often get enormous and it's worth looking at options (like the admin's raw_id_field)

I found something like this in the code:
INCOME_CHOICES = tuple(zip(range(1, 1000000), range(1, 1000000)))
models.IntegerField(choices=INCOME_CHOICES)
I guess there no more mystery :-)

Related

Django MultipleChoiceField with large set of objects (around 100000)

I have a model with ManyToManyField:
class WordList(models.Model):
words = models.ManyToManyField('Word')
These WordList objects should be created from admin, by choosing words (The size of WordList can be different, but, in general, there are should be around 10-20 words in every WordList) By default, Django admin use MultipleChoiceField to render control for ManyToMany field.
There are two problems with it.
The number of Word objects is around 100000, and when I try to edit the WordList object in admin - it takes about 10 seconds on my dev server to load the page. Obviously, almost all time is taken by SELECT * FROM "app_word". That is bad, I am want to speed up it at least to 1-3 seconds.
This is mostly design problem, but the issue reason connected with such large amount of objects. It is hard to find a Word in a drop-down list. I am tried to use [django-easy-select2][https://github.com/asyncee/django-easy-select2] which uses select2.js to add search to ModelChoiceField, but it works really slow and browser starting to eat all RAM and CPU.
Please help. Thank you.
P.S. I am using PostgreSQL
Please try this widget: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.filter_horizontal.
According to the doc:
By default, a ManyToManyField is displayed in the admin site with a
select multiple. However, multiple-select boxes can be difficult to
use when selecting many items. Adding a ManyToManyField to this list
will instead use a nifty unobtrusive JavaScript “filter” interface
that allows searching within the options.
In your code you would do this:
class WordListAdmin(admin.ModelAdmin):
filter_horizontal = ('words',)

Always treat a ForeignKey field like it was in raw_id_fields in Django Admin

This scenario happens way too often in my project:
someone adds a model Foo that has several ForeignKey fields, one of them to refers to model Bar
an admin is added for that model (and works OK)
the code is deployed
on production server, Bar has millions of instances
someone accesses Foo's admin page; Django tries to retrieve all Bars at once (to display them in a combo box) and the server gets overloaded
later the problem gets fixed by editing Foo's admin and adding bar to raw_id_fields.
I'd like to prevent this situation from happening in the future, preferably by somehow stating (once and for all) that Bar has many rows and it should be always treated as if the field referring to it was listed in raw_id_fields in all admin pages. Is this possible somehow?
This is an excelent point. This is a critical issue that can turn down the database and even the web server.
Considering this, I believe the default approach MUST be the raw_id_fields thing. If you know what you are doing, then you change this behavior.
Unfortunately, most of the authors of the admin interfaces libraries disagree of this thought. Not just for Python-Django, but also for other communities like Ruby-Rails.
5 years ago I got tired having the same problem, then I developed the django-smart-autoregister, that do this and also auto configure using another good patterns. Even today I face this problem, so I guess it is worth to take a look.
ps: the library was originally implemented using a modular approach, though you just call some functions that will configure the raw_id_fields for you according to the model field.
From the docs:
ForeignKey is represented by django.forms.ModelChoiceField, which is a
ChoiceField whose choices are a model QuerySet.
ModelChoiceField extends Field, and therefor has a widget property that can be abused
https://github.com/django/django/blob/master/django/forms/fields.py#L49
Add this somewhere in your project files.
from django.forms import ModelChoiceField
from django.contrib.admin.widgets import ForeignKeyRawIdWidget
ModelChoiceField.widget = ForeignKeyRawIdWidget
downside: this is also going to happen on non-admin forms

Django MVT design: Should I have all the code in models or views?

I'm pretty novice so I'll try to explain in a way that you can understand what I mean.
I'm coding a simple application in Django to track cash operations, track amounts, etc.
So I have an Account Model (with an amount field to track how many money is inside) and an Operation Model(with an amount field as well).
I've created a model helper called Account.add_operation(amount). Here is my question:
Should I include inside the code to create the new Operation inside Account.add_operation(amount) or should I do it in the Views?
And, should I call the save() method in the models (for example at the end of Account.add_operation() or must it be called in the views?)
What's the best approach, to have code inside the models or inside the views?
Thanks for your attention and your patience.
maybe you could use the rule "skinny controllers, fat models" to decide. Well in django it would be "skinny views".
To save related objects, in your case Operation I'd do it in the save() method or use the pre_save signal
Hope this helps
Experienced Django users seem to always err on the side of putting code in models. In part, that's because it's a lot easier to unit test models - they're usually pretty self-contained, whereas views touch both models and templates.
Beyond that, I would just ask yourself if the code pertains to the model itself or whether it's specific to the way it's being accessed and presented in a given view. I don't entirely understand your example (I think you're going to have to post some code if you want more specific help), but everything you mention sounds to me like it belongs in the model. That is, creating a new Operation sounds like it's an inherent part of what it means to do something called add_operation()!

Django: Get notified of all changes in database

I was wandering if there's a way to get notified of any changes to objects in a Django database. Right now I just need an email if anybody adds or changes anything but it would be best if I could hook a function triggered by any change and could decide what to do.
Is there an easy way to do it in Django?
Two ideas come to mind:
Override the predefined model method for saving.
Use a signal like post_save.
Here is a good article that talks about the difference between the two things listed above and when to use them:
Django signals vs. custom save()-method
The article was written near the end of 2007, three days after the release of Django 0.96.1. However, I believe the advice the author gives still applies today.

Python - Django - How to handle a multiple page form correctly

I have an application that is used to store vehicle information. I created a Vehicle Model which has many foreign keys including a Consumption Model, Capacity Model, Tires Model, Fuel Model etc.
Multiple Page Form:
When a user wants to add a vehicle to the inventory I wanted to use a multiple page form to break up the steps. So, for example, the first step would be the Vehicle modelform and the second step would be the Fuel modelform. The problem I am running into is storing modelforms over multiple pages without using formwizard.
My Thoughts:
There seems to be no information on how to do this, am I the only one who wants to do this or is the solution blatantly obvious? In other languages I would have stored all the forms in a session and saved them at the end of the process. It seems you can't store a modelform in a session because I get a pickling error (unless I serialize it perhaps?) so I assume that is a no-no. I could save the modelform of a given page to the database before going to the next step but that has multiple issues. i.e. what if the user stops halfway through?
Any explanation on the normal way this is done, or if it is ok to serialize modelforms would be greatly appreciated.
You are looking for the form wizard:
Django comes with an optional “form wizard” application that splits forms across multiple Web pages. It maintains state in hashed HTML fields so that the full server-side processing can be delayed until the submission of the final form.
You might want to use this if you have
a lengthy form that would be too
unwieldy for display on a single page.
The first page might ask the user for
core information, the second page
might ask for less important
information, etc.
More details in the docs.

Categories

Resources