Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django 1.6

Django 1.6

Илья Барышев (Future Colors)

Обзор нового релиза Django 1.6 и небольшое превью миграций в 1.7

Moscow Python Meetup

October 31, 2013
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. ~ 8 месяцев разработки ~ 2250 коммитов ~ 8 микрорелизов

    Чуточку статистики https://www.djangoproject.com/download/1.6c1/tarball/
  2. 1.5.1 Memory leak in QS 1.5.2! 1.4.6 XSS in admin

    posssible XSS in redirect URLs 1.5.3! 1.4.7 Directory traversal in {% ssi %} possible remote code execution 1.5.4! 1.4.8 DoS via password hashers 1.5.4! 1.4.9 Better solution for DoS mitigation Микрорелизы 1.5
  3. Версии Python 2012 Django 1.4 2.5+ 2013 Django 1.5 2.6+

    3.2+ (экспериментально) Django 1.6 2.6+ 3.2+ 2014 Django 1.7 2.7+ 3.2+
  4. Transaction management до 1.6 with  transaction.commit_on_success():        

     #  Наш  выбор   ! with  transaction.commit_manually():          #  Стреляем  себе  в  ногу from  django.db  import  transaction   ! with  transaction.autocommit():          #  Поведение  по-­‐умолчанию
  5. from  django.db  import  transaction   ! users  =  User.objects.filter(name="Ilya")  

    ! with  transaction.commit_on_success():          users.update(is_active=True)                  with  transaction.autocommit():                          #  Raises  IntegrityError                          users.give_prizes()   Вложенность - беда до 1.6
  6. from  django.db  import  transaction   ! def  viewfunc(request):    

         #  This  code  runs  in  autocommit  mode          #  Django’s  default          do_stuff()   !        with  transaction.atomic():                  #  This  code  runs  inside  a  transaction.                  do_more_stuff() Atomic
  7. Test discovery INSTALLED_APPS  =  (          ...

             #3rd-­‐party  apps          'south',          'sorl.thumbnail',          'pytils',          'pymorphy',                    'compressor',          'django_geoip',          'mptt',          'widget_tweaks',          'guardian',          ...   ) Несколько сотен тестов Десятки секунд…
  8. /tests          __init__.py   test_archive.py    

         test_blog_model.py          test_modified.py          test_post_model.py          test_redactor.py          test_views.py          test_cross_post.py #  __init__.py   from  test_archive  import  *   from  test_blog_model  import  *   from  test_modified  import  *   from  test_post_model  import  *   from  test_redactor  import  *   from  test_views  import  *   from  test_cross_post  import  *
  9. Deployment checklist docs Savepoints в SQLite Приятные мелочи BinaryField Model.save()

    optimized Time zone aware aggregation ./manage.py check Улучшен дефолтный шаблон проекта QuerySet.first(),  QuerySet.last() GeoDjango  Forms  API Поддержка Pillow {% firstof %} экранируется в шаблонах ModelAdmin preserves filters
  10. #  -­‐*-­‐  coding:  utf-­‐8  -­‐*-­‐   import  datetime   from

     south.db  import  db   from  south.v2  import  SchemaMigration   from  django.db  import  models   ! ! class  Migration(SchemaMigration):   !        def  forwards(self,  orm):                  #  Adding  field  'Blog.lj_comments_disabled'                  db.add_column('blog_blog',  'lj_comments_disabled',                                              self.gf('django.db.models.fields.BooleanField')(default=False),                                              keep_default=False)   ! !        def  backwards(self,  orm):                  #  Deleting  field  'Blog.lj_comments_disabled'                  db.delete_column('blog_blog',  'lj_comments_disabled')   ! !        models  =  {                  'account.profile':  {                          'Meta':  {'object_name':  'Profile'},                          'avatar':  ('django.db.models.fields.files.ImageField',  [],  {'max_length':  '100',  'blank':  'True'}),                          'biography':  ('django.db.models.fields.TextField',  [],  {'blank':  'True'}),                          'first_name':  ('django.db.models.fields.CharField',  [],  {'max_length':  '1000',  'blank':  'True'}),                          'id':  ('django.db.models.fields.AutoField',  [],  {'primary_key':  'True'}),                          'is_friend':  ('django.db.models.fields.BooleanField',  [],  {'default':  'False'}),                          'is_system':  ('django.db.models.fields.BooleanField',  [],  {'default':  'False'}),                          'last_name':  ('django.db.models.fields.CharField',  [],  {'max_length':  '1000',  'blank':  'True'}),                          'look':  ('django.db.models.fields.files.ImageField',  [],  {'max_length':  '100',  'null':  'True',  'blank':  'True'}),                          'nick':  ('django.db.models.fields.CharField',  [],  {'max_length':  '100',  'blank':  'True'}),                          'subscribe_comments':  ('django.db.models.fields.BooleanField',  [],  {'default':  'True'}),                          'url':  ('django.db.models.fields.URLField',  [],  {'max_length':  '200',  'blank':  'True'}),                          'user':  ('django.db.models.fields.related.OneToOneField',  [],  {'related_name':  "'profile'",  'unique':  'True',  'to':  "orm['auth.User']"}),                          'vanity_mode':  ('django.db.models.fields.BooleanField',  [],  {'default':  'True'}),                          'whois':  ('django.db.models.fields.CharField',  [],  {'max_length':  '255',  'blank':  'True'})                  },                  'auth.group':  {                          'Meta':  {'object_name':  'Group'},                          'id':  ('django.db.models.fields.AutoField',  [],  {'primary_key':  'True'}),                          'name':  ('django.db.models.fields.CharField',  [],  {'unique':  'True',  'max_length':  '80'}),                          'permissions':  ('django.db.models.fields.related.ManyToManyField',  [],  {'to':  "orm['auth.Permission']",  'symmetrical':  'False',  'blank':  'True'})                  },                  'auth.permission':  {                          'Meta':  {'ordering':  "('content_type__app_label',  'content_type__model',  'codename')",  'unique_together':  "(('content_type',  'codename'),)",  'object_name':  'Permission'},                          'codename':  ('django.db.models.fields.CharField',  [],  {'max_length':  '100'}),                          'content_type':  ('django.db.models.fields.related.ForeignKey',  [],  {'to':  "orm['contenttypes.ContentType']"}),                          'id':  ('django.db.models.fields.AutoField',  [],  {'primary_key':  'True'}),                          'name':  ('django.db.models.fields.CharField',  [],  {'max_length':  '50'})                  },                  'auth.user':  {                          'Meta':  {'object_name':  'User'},                          'date_joined':  ('django.db.models.fields.DateTimeField',  [],  {'default':  'datetime.datetime.now'}),                          'email':  ('django.db.models.fields.EmailField',  [],  {'max_length':  '75',  'blank':  'True'}),                          'first_name':  ('django.db.models.fields.CharField',  [],  {'max_length':  '30',  'blank':  'True'}),                          'groups':  ('django.db.models.fields.related.ManyToManyField',  [],  {'to':  "orm['auth.Group']",  'symmetrical':  'False',  'blank':  'True'}),                          'id':  ('django.db.models.fields.AutoField',  [],  {'primary_key':  'True'}),                          'is_active':  ('django.db.models.fields.BooleanField',  [],  {'default':  'True'}),                          'is_staff':  ('django.db.models.fields.BooleanField',  [],  {'default':  'False'}),                          'is_superuser':  ('django.db.models.fields.BooleanField',  [],  {'default':  'False'}),                          'last_login':  ('django.db.models.fields.DateTimeField',  [],  {'default':  'datetime.datetime.now'}),                          'last_name':  ('django.db.models.fields.CharField',  [],  {'max_length':  '30',  'blank':  'True'}),                          'password':  ('django.db.models.fields.CharField',  [],  {'max_length':  '128'}),                          'user_permissions':  ('django.db.models.fields.related.ManyToManyField',  [],  {'to':  "orm['auth.Permission']",  'symmetrical':  'False',  'blank':  'True'}),                          'username':  ('django.db.models.fields.CharField',  [],  {'unique':  'True',  'max_length':  '30'})                  },                  'blog.blog':  {                          'Meta':  {'object_name':  'Blog'},                          'id':  ('django.db.models.fields.AutoField',  [],  {'primary_key':  'True'}),                          'is_active':  ('django.db.models.fields.BooleanField',  [],  {'default':  'False'}),                          'lj_comments_disabled':  ('django.db.models.fields.BooleanField',  [],  {'default':  'False'}),                          'lj_crosspost_enabled':  ('django.db.models.fields.BooleanField',  [],  {'default':  'False'}),                          'lj_login':  ('django.db.models.fields.CharField',  [],  {'default':  "''",  'max_length':  '100',  'blank':  'True'}),                          'lj_pass':  ('django_fields.fields.EncryptedCharField',  [],  {'default':  "''",  'max_length':  '229',  'block_type':  'None',  'cipher':  "'AES'",  'blank':  'True'}),                          'name':  ('django.db.models.fields.CharField',  [],  {'max_length':  '1000'}),                          'owner':  ('django.db.models.fields.related.OneToOneField',  [],  {'related_name':  "'blog'",  'unique':  'True',  'to':  "orm['account.Profile']"}),                          'slug':  ('django.db.models.fields.SlugField',  [],  {'max_length':  '255'}),                          'type':  ('django.db.models.fields.CharField',  [],  {'default':  "'FRIEND'",  'max_length':  '10',  'db_index':  'True'})                  },                  'blog.picture':  {                          'Meta':  {'object_name':  'Picture'},                          'default':  ('django.db.models.fields.BooleanField',  [],  {'default':  'False'}),                          'id':  ('django.db.models.fields.AutoField',  [],  {'primary_key':  'True'}),   Frozen ORM Настоящая миграция
  11. _top from  django.db  import  models   ! class  Author(models.Model):  

           name  =  models.CharField(max_length=500)          featured          =  models.BooleanField()         $  ./manage.py  makemigrations rating  =  models.IntegerField(null=True) Migrations  for  'books':      0003_auto.py:          -­‐  Rename  field  featured  on  author  to   featured_top          -­‐  Add  field  rating  to  author
  12. from  django.db  import  migrations,  models   ! class  Migration(migrations.Migration):  

    !    dependencies  =  [("migrations",  "0001_initial")]          operations  =  [          migrations.RenameField("Author",  "featured",                            "featured_top"),          migrations.AddField("Author",  "rating",                              models.IntegerField(default=0)),      ] Новый формат