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

Мульти-доменность в Django проекте

Мульти-доменность в Django проекте

Алексей Кинёв

Расскажу о реализации мультидоменности в Django-проекте на примере блоговой платформы Qmazi. Про архитектуру, приемы и немного про безопасность.

Moscow Python Meetup
PRO

November 21, 2012
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Мульти-­‐доменность  
    в  Django  проекте  
    Специально  для  
    MoscowDjango  Meetup  #7  
    by  Alexey  Kinyov  [email protected]  

    View Slide

  2. Кто  докладывает  
    •  Алексей  Кинёв,  30  лет,  Москва,  тех.  
    директор  в  компании  КСАН  
    •  Опыт  разработки  на  Python/Django  4  года  
    •  Проекты:  
    – PCNews.ru,  Qmazi.com,  Gallerza.com  
    – django-­‐smarter  
    •  Home  page:  
    – hmp://05bit.com/rudyryk/  

    View Slide

  3. Проблема  /  задача  
    Single  domain:  
    hmp://domain.com///  
     
    Muls  domain:  
    hmp://.domain.com//  
     Single  domain  =>  Muls  domain  

    View Slide

  4. Варианты  решения  
    •  django.contrib.sites  
    –  стандартно,  но  не  то:  1  домен  ó  1  seyngs.SITE_ID  
    •  использовать  Middleware  
    –  звучит  разумно  
    •  использовать  свой  DNS  /  BIND  
    –  «бесплатно»  +  полный  контроль,  но  рискованно,  
    сложно  
    •  использовать  сторонний  DNS  SAS  с  API  
    –  проще,  но  за  деньги  

    View Slide

  5. Выбранное  решение  
    Делаем  Middleware  
    +  PowerDNS.com  
     
    BEST  PRACTICE?  Not  sure.  
    Just  works  J  

    View Slide

  6. Пикантные  подробности  
    Пример  models.py:  
     
    class Channel(models.Model):!
    !slug = models.CharField(max_length=100, unique=True)!
    !title = models.CharField(max_length=200)!
    !# ...!
    !
    class Post(models.Model):!
    !channel = models.ForeignKey(Channel)!
    !# ...!

    View Slide

  7. Пикантные  подробности  
    Пример  urls.py  
     
    urlpatterns = ('',!
    !
    # host based views!
    url(r'^~/(?P[^/]+)/$',!
    ! !channel_view),!
    url(r'^~/(?P[^/]+)/post/(?P\d+)/$',!
    ! !post_view),!
    # ...!
    )!
    !

    View Slide

  8. Пикантные  подробности  
    Пример  views.py:  
     
    def post_view(request, host, pk):!
    !# get 'myblog' of 'myblog.qmazi.com'!
    slug = host.split('.', 1)[0]!
    !post = get_objects_or_404(Post, channel__slug=slug, pk=pk)!
    return render(request, 'channel/post.html', {'post': post})!
    hmp://qmazi.com/~/myblog.qmazi.com/post/20/  
    host   pk  

    View Slide

  9. Пикантные  подробности  
    !
    class MultiHostMiddleware(object):!
    def process_request(self, request): !
    # settings.SITE_HOST = 'domain.com’ # main domain!
    if request.get_host() != settings.SITE_HOST:!
    ! !request.path = '/~/%s/%s' % (!
    ! !request.get_host(),!
    ! !request.path.lstrip('/'))!
    ! !request.path_info = request.path!
    The  trick:  подменяем  request.path_info  

    View Slide

  10. Profit  J  
    hUp://myblog.qmazi.com/post/20/  
     
     
    /~/myblog.qmazi.com/post/20/  
     
     
    post_view  

    View Slide

  11. Слабые  места  
    1.  Нельзя  использовать  reverse  для  
    генерации  host-­‐based  адресов  
    2.  Усложнение  views  
    Решается  адекватным  набором  u]ls.  

    View Slide

  12. Развитие  решения  
    «Прячем»  служебные  url’ы:  
    !
    def post_view(request, host, pk):!
    !if not settings.DEBUG_HOSTS:!
    ! !if host != request.get_host():!
    ! ! !raise Http404!
    !# ...!
     
    Подключаем  любой  домен:  
    !
    def post_view(request, host, pk):!
    !# ...!
    !channel = get_channel_by_host(host) # my utils!
    !post = get_objects_or_404(Post, channel=channel, pk=pk)!
    !# ...!
     

    View Slide

  13. Спасибо!  
    Вопросы?  

    View Slide