Django小笔记
06 November 2016
Django Notes
General
- Chinese support
- language code in settings.py
- utf-8 coding in any .py
- encoding header in html templates
- use django models in scrapy projects:
def setup_django_env(path): import imp, os from django.core.management import setup_environ f, filename, desc = imp.find_module('settings', [path]) project = imp.load_module('settings', f, filename, desc) setup_environ(project) # Add django project to sys.path import sys sys.path.append(os.path.abspath(os.path.join(path, os.path.pardir))) setup_django_env('/home/zhichu/Projects/trip_proj/trip_proj/gotrip/gotrip/')
Model/Form/Query
- .
.filter
returns a queryset, i.e. you need to do a forloop to get individual instances verbose_name
will be overriden if formfield is re-defined in forms.py; uselabel
for form field insteadclass ItineraryForm(ModelForm): start_date = forms.DateField(('%Y/%m/%d',), label = u'checkin_date', widget = forms.DateTimeInput(format='%Y/%m/%d', attrs={ 'class':'input', 'size':'10' }))
- date format should match between jquery widget and formfield setting
- for using
contenttype
, see my SO question Django: using ContentType vs multi table inheritance andtrip/models.py
andtrip/views.py
hotelstay_ctype = ContentType.objects.get_for_model(HotelStay) trip_event_list = TripEvent.objects.filter(content_type=hotelstay_ctype) for trip_event in trip_event_list: print trip_event.content_object.checkin_date
- filter objects by date:
queryset=Itinerary.objects.filter(end_date__lt=date.today())
- filter ModelForm's ForeignKey field during initialization, by passing
user=request.user
through*kwargs
to form's__init__()
method:# in forms.py class HotelStayForm(ModelForm): ... def __init__(self, *args, **kwargs): #set initial value for field itinerary user = kwargs.pop('user', '') super(HotelStayForm, self).__init__(*args, **kwargs) # only show itineraries belonging to request.user self.fields['itinerary'].queryset = Itinerary.objects.filter(user=user) # in views.py @login_required() def add_hotelstay(request): if request.method == 'POST': # If the form has been submitted... form = HotelStayForm(request.POST, user=request.user) # A form bound to the POST data if form.is_valid(): # All validation rules pass # Process the data in form.cleaned_data # ... else: form = HotelStayForm(user=request.user) # user kwargs used in form to set initial value for itinerary field return render_to_response('trip/add_itinerary.html', { 'form': form}, context_instance=RequestContext(request) )
- attaching multiple models to a model, and show them in admin site, see this http://stackoverflow.com/questions/537593/multiple-images-per-model
- aggregate over reverse relationship and sort by aggregated value
st_count=TrainStationDetail.objects.all().annotate(line_count=Count('trainlinedetail')).order_by('-line_count')
View/Template
- passing variables from templates to callable methods is bad for security/maintainability; use
template tags
instead - use
reverse_lazy()
instead ofreverse()
forsuccess_url
in generic views - to use message in generic views, override
form_valid()
method - override
get_queryset()
to check object ownership decorator
can be added tourlConf
ordispatch
method for generic views- use multiple submit buttons:
<input class="button" type="submit" name="_delete" value="finish"> <input class="button" type="submit" name="_back" value="don't delete"> if '_back' in self.request.POST:
- To update RequestContext(request) with extra context,
context = RequestContext(request) context.update({'friend_list':friend_list})
see this SO question concatenate two dict for some related discussion.
- chaining template filters
- showing localtime in template
// gets localtime // gets utc time
Test
- Simulating user login in a unittest
from django.contrib.auth.models import User from django.test import TestCase from django.test.client import Client class TripTestCase(TestCase): def setUp(self): self.client = Client() self.test_user = User.objects.create_user('testuser', 'test@test.com', 'password') def user_login(self): self.client.login(username='testuser', password='password') def tearDown(self): self.test_user.delete() class SimpleTest(TripTestCase): def test_list_itinerary_view(self): self.user_login() resp = self.client.get('/trip/list_itinerary/') self.assertEqual(resp.status_code, 200)
Celery
pytz
needs to be installed to use celery beat- run periodic background tasks:
./manage.py celery beat --loglevel=INFO
run worker:
./manage.py celery worker
using custom logging
-l INFO -f worker.log
(using custom logging in celery seems very hard, if not using some nasty hack. Currently using celery-provided logging. The only complaint is worker.log gets DEBUG-level messages from MainProcess. Will look for a better logging solution in the future.)
south
- use south to migrate data after adding a field to a model:
- before changing the model,
./manage.py schemamigration <appname>
- after changing the model,
./manage.py schemamigration <appname>; ./manage.py migrate <appname>
- before changing the model,
- for a legacy app, run
./manage.py convert_to_south <appname>
tastypie
- See this SO thread for methods to toggle 'full' through url
deployment
- uwsgi+nginx:
sudo apt-get install nginx apt-get install build-essential python-dev libxml2-dev # uwsgi dependency pip install uwsgi bin/uwsgi --socket /tmp/uwsgi.sock --wsgi-file /mnt/scratch/test.py --chmod-socket=666 # serve django bin/uwsgi --socket /tmp/uwsgi.sock --chdir /mnt/scratch/testapp/testdeploy/ --wsgi-file /mnt/scratch/testapp/testdeploy/testdeploy/wsgi.py --virtualenv /usr/virtualenv --chmod-socket=666
- verify nginx conf file:
/usr/sbin/nginx -t -c conf_name.conf
- uwsgi configurations
- use
master=true
andpidfile
for easier management, e.g.uwsgi --reload pid_file
- use
stat\_server
for worker monitoring# in uwsgi.ini stats = /tmp/uwsgi_stat.sock # in shell $ uwsgitop /tmp/uwsgi_stat.sock
- read uwsgitop output
WID worker id % percentage of served requests by the worker PID process id of the worker REQ number of managed requests EXC number of raised exceptions SIG number of managed uwsgi signals (NOT unix signals !!!) STATUS can be idle, busy, pause, cheaped or sig AVG average response time for the worker RSS RSS memory (need –memory-report) VSZ address space (need –memory-report) TX transmitted data RunT running time
- use
blog comments powered by Disqus