lo nuevo de django 1.7 y 1.8
TRANSCRIPT
Lo nuevo de Django
Pedro Burón
Django Unchained
Pedro Burón
Agenda
• Django 1.7
– App loading framework
– Forms
– Querysets
– Schema Migrations
Agenda
• Django 1.8
– Postgres specifics
– Conditional expressions
– Template Engines
Agenda
• Django 1.7
– Schema Migrations
• Django 1.8
– Conditional expressions
– Template Engines
App Loading
Framework
AppConfig
from django.apps import AppConfig
class RockNRollConfig(AppConfig):
name = 'rock_n_roll'
verbose_name = "Rock ’n’ roll”
class GypsyJazzConfig(RockNRollConfig):
verbose_name = "Gypsy jazz“
INSTALLED_APPS = [
'anthology.apps.GypsyJazzConfig',
# ...
]
Forms
Forms add error
def clean(self):
cleaned_data = super(ContactForm, self).clean()
cc_myself = cleaned_data.get("cc_myself")
subject = cleaned_data.get("subject")
if cc_myself and subject and "help" not in subject:
msg = u"Must put 'help' in subject."
self.add_error('cc_myself', msg)
self.add_error('subject', msg)
Querysets
Queryset as managers
class MyQueryset(models.QuerySet):
def published(self):
return self.filter(published=True)
class MyModel(models.Model):
objects = MyQueryset.as_manager()
...
Schema Migrations
Thanks to:
Andrew Godwin
Migrations directory
$ ./manage.py startapp myapp$ tree
.
|-- djangounchained
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
|-- manage.py
`-- myapp
|-- admin.py
|-- migrations|-- models.py
`-- views.py
Models
# models.py
class Entry(models.Model):
title = models.CharField(…)
content = models.TextField()
slug = models.SlugField(…)
Make migrations
$ ./manage.py makemigrations myapp
The Migration File
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.CreateModel(
name='Entry',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('title', models.CharField(max_length=200)),
('content', models.TextField()),
('slug', models.SlugField(unique=True, max_length=200)),
],
options={
},
bases=(models.Model,),
),
]
Migrate
$ ./manage.py migrate myapp
The Operations
• CreateModel
• DeleteModel
• AddField
• AlterField
• AlterModelTable
• RunSQL
• RunPython
CreateModel
migrations.CreateModel(
name='Person',
fields=[
('id', models.AutoField(verbose_name='ID',
serialize=False, auto_created=True,
primary_key=True)),
('full_name’,models.CharField(max_length=100)),
],
options={},
bases=(models.Model,),
)
AddField
dependencies = [
('people', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='person',
name='first_name',
field=models.CharField(default='',
max_length=50),
preserve_default=False,
),
RunPython
def split_names(apps, schema_editor):
Person = apps.get_model('people.Person')
for person in Person.objects.all():
full_name = person.full_name.split(' ')
person.first_name = full_name[0:-1]
person.last_name = last_name[-1]
person.save()
migrations.RunPython(
split_names,
merge_names
)
RemoveField
dependencies = [
('people', '0003_split_full_name'),
]
operations = [
migrations.RemoveField(
model_name='person',
name='full_name',
),
]
DJANGO 1.8
luego, muy luego...
Postgres Specific
ArrayField
class ChessBoard(models.Model):
board = ArrayField(
ArrayField(
models.CharField(max_length=10, blank=True),
size=8,
),
size=8,
)
HStoreField
class Dog(models.Model):
name = models.CharField(max_length=200)
data = HStoreField()
>>> Dog.objects.create(name='Rufus',
data={'breed': 'labrador'})
>>> Dog.objects.filter(
data__breed='labrador')
RangeField
class Event(models.Model):
name = models.CharField(max_length=200)
ages = IntegerRangeField()
>>> Event.objects.create(name='Soft play',
ages=(0, 10))
>>> Event.objects.create(name='Pub trip',
ages=(21, None))
>>> Event.objects.filter(
ages__contains=NumericRange(4, 5))
[<Event: Soft play>]
Unaccent!
User.objects.filter(
first_name__unaccent__startswith="Revolv")
Conditionals
Expressions
SQL Conditional Field
SELECT
”client"."name",
CASE
WHEN ”client"."account_type" = 'G’
THEN '5%'
WHEN ”client"."account_type" = 'P’
THEN '10%' ELSE '0%'
END AS "discount"
FROM
”client"
Case, When
>>> Client.objects.annotate(
... discount=Case(
... When(account_type=Client.GOLD,
... then=Value('5%')),
... When(account_type=Client.PLATINUM,
... then=Value('10%')),
... default=Value('0%'),
... output_field=CharField(),
... ),
... ).values_list('name', 'discount')
Conditional Update
for cl in Client.objects.all():
if cl.registered <= a_year_ago:
client.account_type = GOLD
elif cl.registerd <= a_month_ago:
client.account_type = PLATINUM
else:
client.account_type = REGULAR
client.save()
Conditional Update
Client.objects.update(
account_type=Case(
When(
registered_on__lte=a_year_ago,
then=Value(Client.PLATINUM)),
When(
registered_on__lte=a_month_ago,
then=Value(Client.GOLD)),
default=Value(Client.REGULAR)
),
)
Template Engines
TEMPLATES setting
TEMPLATES = [
{
'BACKEND':
'django.template.backends.django.DjangoTemplates',
#'django.template.backends.jinja2.Jinja2'
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {},
},
]
Multiple Template Engines
TEMPLATES = [
{
’NAME': 'django'
'BACKEND':
'django.template.backends.django.DjangoTemplates',
},
{
’NAME': ’jinja2'
'BACKEND':
'django.template.backends.jinja2.Jinja2',
},
]
My Custom Engine
MyEngine
class MyEngine(BaseEngine):
app_dirname = 'dummy'
def __init__(self, params):
...
def from_string(self, template_code):
...
def get_template(self, template_name):
...
Template Wrapper
class Template(object):
def __init__(self, template):
...
def render(self, context=None,
request=None):
...