Online: malloc47.com/posscon2013/
Ph.D. candidate in the Department of Computer Science and Engineering at the Univeristy of South Carolina
Researcher -○- Software Developer -○- Python Programmer
Background on Django -○- Demystifying Concepts
django.contrib.*
)
Model | = | the data itself |
Template | = | how the data is presented |
View | = | which data is presented |
https://docs.djangoproject.com/en/dev/misc/design-philosophies/
> django-admin.py startproject myproj
> ./manage.py startapp myapp
|
|
Recommended
the non-root way
pythonbrew | — | build/install
local copies of Python, independent of the system
(forked as pythonz ) |
virtualenv | — | local environment for installing python packages |
pip | — | Python package manager |
pip install
django |
requirements.txt | — | machine-readable list of dependencies for your project |
Django==1.4.3
South==0.7.6
scss==0.8.72
simplejson==2.6.1
which can be read by pip
pip install -r requirements.txt
Request → urls.py → views.py function → <template>.html
GET request for /stuff/
urls.py
urlpatterns = patterns('',
(r'^stuff/$', views.stuff_handler),
)
views.py
def stuff_handler(request):
return render(request, 'stuff.html',
{'name': request.user.username})
stuff.html
<html>
<head><title>Page o' Stuff</title></head>
<body>
<p> Your name is {{ name }} </p>
</body></html>
models.py
class Person(models.Model):
account = models.ForeignKey('django.contrib.auth.models.User')
name = models.CharField(max_length=64)
cash = models.BigIntegerField()
views.py
def stuff_handler(request):
me = Person.objects.filter(account=request.user)
return render(request, 'stuff.html', {'me': me})
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
class CommonMiddleware(object):
def __init__():
pass # only called once
def process_request(self, request):
pass
def process_view(self,request,view_func,view_args,view_kwargs):
pass
def process_template_response(self, request, response):
pass
def process_response(self, request, response):
pass
def process_exception(self, request, exception):
pass
class CommonMiddleware(object):
def process_request(self, request):
if 'HTTP_USER_AGENT' in request.META:
for ua in settings.DISALLOWED_USER_AGENTS:
if ua.search(request.META['HTTP_USER_AGENT']):
logger.warning('Forbidden: %s', request.path,
extra={
'status_code': 403,
'request': request
}
)
return http.HttpResponseForbidden('Forbidden')
class BrokenLinkEmailsMiddleware(object):
def process_response(self, request, response):
if response.status_code == 404 and not settings.DEBUG:
# sanity checks go here
ua = request.META.get('HTTP_USER_AGENT', '')
ip = request.META.get('REMOTE_ADDR', '')
mail_managers(
"Broken link on %s" % (request.get_host(),),
"""Referrer: %s
Requested URL: %s
User agent: %s
IP address: %s
""" % (request.META.get('HTTP_REFERER', ''),
request.get_full_path(), ua, ip),
fail_silently=True)
return response
from bs4 import BeautifulSoup
class BeautifulMiddleware(object):
def process_response(self, request, response):
if response.status_code == 200:
if response["content-type"].startswith("text/html"):
beauty = BeautifulSoup(response.content)
response.content = beauty.prettify()
return response
Content
<html><p>Some data<p>Moar data
Beautified
<html>
<body>
<p> Some data </p>
<p> Moar data </p>
</body>
</html>
Content
Pure text
Beautified
<html>
<body>
<p>Pure text</p>
</body>
</html>
class CreationDateTimeField(DateTimeField):
def __init__(self, *args, **kwargs):
kwargs.setdefault('editable', False)
kwargs.setdefault('blank', True)
kwargs.setdefault('default', datetime.now)
DateTimeField.__init__(self, *args, **kwargs)
instead of
class Person(models.Model):
create = DateTimeField(editable=False,
blank=True,
default=datetime.now)
we get
class Person(models.Model):
create = CreationDateTimeField()
class ExpireField(DateTimeField):
def __init__(self, verbose_name=None, name=None, **kwargs):
# get attribute
self.duration = kwargs.pop('duration')
# check type
if not isinstance(self.duration, timedelta):
raise FieldError
super(ExpireField, self).__init__(verbose_name,
name,
**kwargs)
allows
class Person(models.Model):
expire_time = ExpireField( duration=timedelta(hours=2) )
This snippet does nothing... yet
class UUIDField(CharField):
def __init__(self, verbose_name=None, name=None, **kwargs):
kwargs.setdefault('max_length', 36)
self.empty_strings_allowed = False
kwargs['blank'] = True
kwargs.setdefault('editable', False)
CharField.__init__(self, verbose_name, name, **kwargs)
def contribute_to_class(self, cls, name):
if self.primary_key:
assert not cls._meta.has_auto_field, "More than one PK"
super(UUIDField, self).contribute_to_class(cls, name)
cls._meta.has_auto_field = True
cls._meta.auto_field = self
else:
super(UUIDField, self).contribute_to_class(cls, name)
def pre_save(self, model_instance, add):
value = super(UUIDField, self).pre_save(model_instance,add)
if add:
value = force_unicode(uuid.uuid4())
setattr(model_instance, self.attname, value)
return value
def get_internal_type(self):
return CharField.__name__
class PickledObjectField(models.Field):
def __init__(self, *args, **kwargs):
kwargs.setdefault('null', True)
kwargs.setdefault('editable', False)
super(PickledObjectField, self).__init__(*args, **kwargs)
def to_python(self, value):
if value is not None:
value = pickle.loads(b64decode(value))
return value
def get_db_prep_value(self, value):
if value is not None:
value = force_unicode(b64encode(pickle.dumps(value)))
return value
def get_db_prep_lookup(self, lookup_type, value):
if lookup_type not in ['exact', 'in', 'isnull']:
raise TypeError('Lookup type %s is not supported.' % lookup_type)
return super(PickledObjectField, self).get_db_prep_lookup(lookup_type, value)
def value_to_string(self, obj):
value = self._get_val_from_obj(obj)
return self.get_db_prep_value(value)
def get_internal_type(self):
return 'TextField'
__metaclass__ = models.SubfieldBase # to_python will be called
manage.py ⇒ django-admin.py
./manage startapp
./manage syncdb
./manage shell
./manage runserver localhost:8000
./manage changepassword
./manage help
New commands:
appname/management/commands/command_name.py
cron
jobsRemember ExpireField
class Command(BaseCommand):
def handle(self, *args, **options):
# get all models that have an ExpireField
models = [m for m in django.db.models.get_models()
if any(type(f) is ExpireField for f in m._meta.fields)]
for model in models:
field = next(f for f in model._meta.fields
if type(f) is ExpireField )
filter_args = {'{0}__{1}'.format(field.name, 'lt'):
(datetime.now() - field.duration),}
# delete all the old objects
q = model.objects.filter(**filter_args)
q.delete()
./manage expire
optparse
Argumentsclass Command(BaseRunserverCommand):
option_list = BaseRunserverCommand.option_list + (
make_option('--sass',
action='store_true',
dest='sass',
default=False,
help='process all sass files in project'),
)
def inner_run(self, *args, **options):
if options['sass']:
print('Processing SASS files...')
files = find_scss('assets/')
for f in files:
print('==> Converting ' + f)
with open(os.path.splitext(f)[0]+'.css','w') as h:
h.write(parser.load(f))
# continue with the runserver command
super(Command, self).inner_run(*args, **options)
def find_scss(top):
return reduce(
list.__add__,
[[os.path.join(root, f)
for f in files
if f.endswith('.scss') or f.endswith('.sass')]
for root, dirs, files
in os.walk(top)],
[])
./manage runserver --sass
importd — http://pythonhosted.org/importd/
from importd import d # the d is for Django
@d("/")
def index(request):
return d.HttpResponse("hello world")
jython — https://code.google.com/p/django-jython/
jython manage.py war
cheat sheet — http://media.revsys.com/images/django-1.4-cheatsheet.pdfs
debug toolbar — https://github.com/django-debug-toolbar/django-debug-toolbar