What are the worst mistakes made using Django framework, that you have noticed? Have you seen some real misuses, that maybe should go as warnings to the Django docs?
I tried to append items to my session without copying them out, appending the items, and then adding the list back to the session.
This mistake is on a NewbieMistakes page, so hopefully I'm in good company.
This is the correct way to do it, in case anyone is curious.
sessionlist = request.session['my_list']
sessionlist.append(new_object)
request.session['my_list'] = sessionlist
Not splitting stuff up into multiple applications. It's not so much about reusability as it is about having a dozen models, and over 100 views in one app, it's damned unreadable. Plus I like to be able to scan my urls.py file easily to see where a URL points, when I have 100 URLs that gets harder.
I think the biggest problem is that people try to code as if this were Java/C: They try to create overly generic applications that need never be changed when future requirements change (which is necessary for Java/C because those apps aren't so easy to change/redesign). What results is a hideously complicated application, which is inflexible and impossible to maintain.
It's just not necessary in Django: just write for today's requirements, build reusable apps with defined, specific tasks and make changes when needed. More and more often I find myself trying to write things as simply as possible, avoiding overly complicated designs at all costs.
I first and fore most mistake start writing python code without reading PEP. The worst thing i would quote are
NOTE: Things I am quoting here are DONT'S
1
foo = bar
foobar = bar
foobarbuz = bar
2
foo = "foo"
bar = "bar"
foobar = foo + bar //string concat
3
foo = [1,2,3,4,5,6]
foo_ = []
for bar in foo:
foo_.append(bar)
4
writing import statements with project name
from projectname.appname.models import model
5
Trying to use view like normal python functions
Update: or having too much logic in the view rather moving something to the helper(utils), I dint mean here its a bad practice to make a redirect, There are people who write helper functions in the view.
6
Function/method without a docstring and using namespace no way connected to the context.
Too much logic in views.
I used to write views that would struggle to fit in 40 lines. Now I consider more than 2-3 indentation levels, 10 or so LOC or a handful of inline comments in a view to be code smells.
The temptation is to write minimal models, figure out your url routing, then do everything else in the view. In reality, you should be using model methods, managers, template tags, context processors, class-based views with abstract base views... anything to keep the view code simple and readable. Logic around saving forms should go in Form.save(). Logic repeated at the start or end of multiple views should go in decorators. Reused display logic should go in include
d templates, template tags, and filters.
Long views are hard to read, understand, and debug. Learn to use the other tools in you toolkit any you'll save yourself and your team a lot of pain.
Monkeying around with pre-save and post-save events.
If you can't simply do it in
save
, you should probably rethink what you're trying to do. After all, it's just a relational database under the hood. If what you're doing gets too complex, you'll have ORM mapping issues.Trying to write uber-generic -- one view does it all -- functionality. View functions are functions for a reason. They can use modules, packages, objects, other functions, etc. They can be short and similar without it being a code smell.
If you need to use 10 lines of code to construct the uber-generic-do-it-all object and it would have been a 12-line view function without the uber-generic-do-it-all object, then the uber-object isn't helping.
Imposing too much super-sophisticated object class design on the ORM model classes. If it requires abstract base classes or metaclasses, it won't do well in the ORM layer.
Failing to make use of
tests.py
and the test client to create complete unit tests of whatever it's claimed that the application does.
Worst facepalm moment...returning an unlimited query, which happened to be several hundred thousand rows long. It was in a rarely used bit of code, so didn't happen often, but when it did it brought down the server.
Always make sure your query results are limited, i.e.:
results = MyModel.query.all()[:100]
not:
results = MyModel.query.all()
or use an iterator:
for result in MyModel.query.iterator():
My worst mistake was using absolute imports like <project_name>.<app_name>.models
rather than <app_name>.models
. This way when I made a branch and wanted to check it out in different directory (like having and -stable of my project), it wouldn't run. I managed to revert in one project and use only relative imports in one project, but in another, larger one, we have to stick with it (we have there both absolute and relative). I won't make this mistake again.
I've experienced a worst practice : use something else that the default id as primary key of model.
It looked as a good idea but it caused some problems in the administration web site and it was difficult to restore the id as primary key on an existing database.
I think that there is no specific case that are specific enough to cause these problems. I recommend to keep the id of your model as it is by default.
See http://stackoverflow.com/questions/2055784/what-is-the-best-approach-to-change-primary-keys-in-an-existing-django-app for details
Not using raw_id fields for a key to 10000+ objects, then wondering why visiting the Admin brings a server to its knees