Docker-mailman: django์—์„œ example.com์„ ๊ธฐ๋ณธ ์‚ฌ์ดํŠธ๋กœ ์ œ๊ฑฐ

์— ๋งŒ๋“  2017๋…„ 04์›” 21์ผ  ยท  9์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: maxking/docker-mailman

ํ˜„์žฌ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‚˜ํƒ€๋‚˜๋ฉด ๊ธฐ๋ณธ ์‚ฌ์ดํŠธ๊ฐ€ example.com์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค (์–ด๋–ค ์ด์œ ๋กœ ๋“ ).

์ด๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์‚ฌ์ดํŠธ ID๋ฅผ ์‚ฌ์šฉ์ค‘์ธ ์‹ค์ œ ๋„๋ฉ”์ธ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ์ง€์นจ์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

bug documentation web

๋ชจ๋“  9 ๋Œ“๊ธ€

๋” ๋‚˜์œ ๊ฒƒ์€ ์‚ฌ์ดํŠธ ๋ชฉ๋ก์—์„œ example.com์„ ์‚ญ์ œํ•˜๋ฉด '์„œ๋ฒ„ ์˜ค๋ฅ˜ (500)'๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์„ค์น˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ mailman-web ๋กœ๊ทธ์˜ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python2.7/site-packages/postorius/views/list.py", line 593, in list_index
    'domain_count': len(choosable_domains)})
  File "/usr/local/lib/python2.7/site-packages/django/shortcuts.py", line 30, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "/usr/local/lib/python2.7/site-packages/django/template/loader.py", line 68, in render_to_string
    return template.render(context, request)
  File "/usr/local/lib/python2.7/site-packages/django/template/backends/django.py", line 66, in render
    return self.template.render(context)
  File "/usr/local/lib/python2.7/site-packages/django/template/base.py", line 206, in render
    with context.bind_template(self):
  File "/usr/local/lib/python2.7/contextlib.py", line 17, in __enter__
    return self.gen.next()
  File "/usr/local/lib/python2.7/site-packages/django/template/context.py", line 236, in bind_template
    updates.update(processor(self.request))
  File "/usr/local/lib/python2.7/site-packages/django_mailman3/context_processors.py", line 33, in common
    context["site_name"] = get_current_site(request).name
  File "/usr/local/lib/python2.7/site-packages/django/contrib/sites/shortcuts.py", line 15, in get_current_site
    return Site.objects.get_current(request)
  File "/usr/local/lib/python2.7/site-packages/django/contrib/sites/models.py", line 65, in get_current
    return self._get_site_by_id(site_id)
  File "/usr/local/lib/python2.7/site-packages/django/contrib/sites/models.py", line 35, in _get_site_by_id
    site = self.get(pk=site_id)
  File "/usr/local/lib/python2.7/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 385, in get
    self.model._meta.object_name
DoesNotExist: Site matching query does not exist.

@ulrith ์˜ˆ, Django์˜ ์„ค์ •์—์„œ ๊ธฐ๋ณธ SITE_ID ๋ฅผ ์‚ฌ์šฉ์ค‘์ธ ์‚ฌ์ดํŠธ๋กœ ๋ณ€๊ฒฝํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ์ด ๊ฐ’์€ ์ปจํ…Œ์ด๋„ˆ์˜ settings.py ์ด๋ฉฐ example.com์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

settings_local.py ์˜ ๋„๋ฉ”์ธ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” 2๋กœ ๋ณ€๊ฒฝํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
SITE_ID=2

@maxking example.com์„ ์‹ค์ œ ๋„๋ฉ”์ธ์œผ๋กœ ๋Œ€์ฒด ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ด ์ฃผ์„ ์—์„œ ์–ธ๊ธ‰ ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปจํ…Œ์ด๋„ˆ์˜ SQL ์ฟผ๋ฆฌ๋กœ ... ๋„์™€ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@ulrith ์˜ˆ, Django ๋ช…๋ น ์ค„์€ ํ”„๋กœ๋•์…˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ๋„ ์›ํ•˜๋Š” ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜์žˆ๋Š” python REPL๋กœ ์‚ฌ์šฉ์ž๋ฅผ ๋“œ๋กญํ•ฉ๋‹ˆ๋‹ค ;-)

maxking<strong i="7">@mailman</strong>:~$ docker exec -it mailman-web python manage.py shell
Python 2.7.13 (default, Jun 21 2017, 18:14:15) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.db import models
>>> from django.contrib.sites.models import Site
>>> Site.objects.all()
<QuerySet [<Site: lists.araj.me>]>
>>> Site.objects.create(name='Random Domain', domain='mail.araj.me')
<Site: mail.araj.me>
>>> Site.objects.all()
<QuerySet [<Site: lists.araj.me>, <Site: mail.araj.me>]>
>>> for each in Site.objects.all():
...     print(each.domain, each.id)
... 
(u'lists.araj.me', 2)
(u'mail.araj.me', 3)

์ด์— ๋Œ€ํ•ด ๋” ์ฝ์–ด์•ผํ•œ๋‹ค๋ฉด Django์˜ ์‚ฌ์ดํŠธ ํ”„๋ ˆ์ž„ ์›Œํฌ์— ๋Œ€ํ•œ ๋งํฌ๊ฐ€

@maxking ์‚ฌ์‹ค ์ €๋Š” ํŒŒ์ด์ฌ์— ์ต์ˆ™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ ์„ค์น˜๋œ Mailman 3์— ๋Œ€ํ•ด Site : example.com์„ Site : mydomain.tld๋กœ ๋Œ€์ฒด ํ•  ์ฝ”๋“œ ์Šค ๋‹ˆํŽซ (์ด์ƒ์ ์œผ๋กœ๋Š” ํ•˜๋‚˜์˜ ๋ผ์ด๋„ˆ)์„ ์•Œ๋ ค์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์ข‹์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ Django๋Š” ๊ธฐ๋ณธ examples.com ์‚ฌ์ดํŠธ ์ž์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ค์ œ๋กœ์ด ๋™์ž‘์„ ์ค‘์ง€ ํ•  ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์‹œ์ž‘ํ•˜๋Š” ๋™์•ˆ ์ƒˆ ์›น ์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค๋ ค๋Š” ๊ฒฝ์šฐ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ด๊ฒƒ์„ํ•˜๊ธฐ์œ„ํ•œ "์˜ฌ๋ฐ”๋ฅธ"๋ฐฉ๋ฒ•์€ Django์˜ ์กฐ๋ช…๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Fixture๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์–ด๋–ค ์šฉ๋„๋กœ๋“  ํ•˜๋“œ ์ฝ”๋”ฉ ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ JSON, YAML ๋˜๋Š” XML๋กœ ์ง๋ ฌํ™” ๋œ ํŒŒ์ผ์„ ์ˆ˜๋™์œผ๋กœ ๋งŒ๋“ค๊ณ  python manage.py loaddata <nameoffixture> ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด django๊ฐ€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด :

์•„๋ž˜ ํŒŒ์ผ์€ fixtures/gen_site.yaml ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

- model: sites.Site
  pk: 100
  fields:
    domain: gmail.com
    name: Google

๊ทธ๋Ÿฐ ๋‹ค์Œ python manage.py loaddata gen_site ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์‚ฌ์ดํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ๋‹น์‹ ์€ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด SITE_ID=100 ์—์„œ settings_local.py ์™€ ์‚ฌ๋ฌผ์ด ์ž‘๋™ํ•œ๋‹ค!

๊ทธ๋Ÿฌ๋‚˜ ์‹œ์ž‘์‹œ ์‚ฌ์šฉ์ž ์ง€์ • ๋ช…๋ น์„ ์‹ค์ œ๋กœ ์‹คํ–‰ํ•˜๋Š” ์‰ฌ์šด ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ง€๊ธˆ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (Docker ์šฉ์–ด๋กœ๋Š” ์ง„์ž… ์ ์ด๋ผ๊ณ ๋„ ํ•จ). ๋‚˜๋Š” ๊ทธ ๋ฌธ์ œ๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ์ด์Šˆ # 61์„ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค.

  • ๋‘ ๋ฒˆ์งธ ์˜ต์…˜์€ ๋‹ค์Œ ๋ช…๋ น์„ ์ˆ˜๋™์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
python manage.py shell -c "from django.contrib.sites.models import Site; mysite,_=Site.objects.get_or_create(id=101, name='mysite.tld', domain='mysite.tld'); print(mysite.id, mysite.name)"

์œ„์˜ ๋ช…๋ น์€ django ์šฉ์ด๋ฏ€๋กœ ์œ„์˜ ๋ช…๋ น ์•ž์— docker-compose exec -T mailman-web ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
์ด ๋ช…๋ น์€ mysite.tld ๋ผ๋Š” ์ƒˆ ์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋˜ํ•œ id ๋ฅผ ์ธ์‡„ ํ•œ ๋‹ค์Œ SITE_ID=101 ์•„๋ž˜์— ์ž…๋ ฅํ•˜๊ณ  Django ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ช…๋ น์€ ์‚ฌ์ดํŠธ๊ฐ€ ์ด๋ฏธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์žˆ๋Š” ๊ฒฝ์šฐ ์‹คํŒจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ฒซ ๋ฒˆ์งธ๋กœ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํšจ๊ณผ๊ฐ€ ์ ์šฉ๋˜๊ณ  (์ฒ˜์Œ์—๋งŒ ํ•ด๋‹น๋˜์ง€๋งŒ ๋˜‘๊ฐ™์ด ๋‚˜์˜๋‹ค) ๋‘ ๋ฒˆ์งธ๋กœ settings_local.py ๋ฅผ ์ž๋™์œผ๋กœ ํŽธ์ง‘ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋ผ๊ณ  ๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. sed ๋˜๋Š” awk ๋งˆ๋ฒ•์„ ์“ฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ˆ˜๋™ ๊ฐœ์ž…์—†์ด ์ƒˆ๋กœ์šด SITE_ID settings_local.py ์„ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์„ธ ๋ฒˆ์งธ ์˜ต์…˜์€ example.com ๋„๋ฉ”์ธ์„ ํŽธ์ง‘ํ•˜๊ณ  ์›ํ•˜๋Š” ๋„๋ฉ”์ธ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
python manage.py shell -c "from django.contrib.sites.models import Site; Site.objects.filter(domain='example.com').update(name='My Site', domain='mysite.tld')"

์ด๊ฒƒ์€ ์–ด๋””์—์„œ๋‚˜ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜์ง€ ์•Š์ง€๋งŒ ๋กœ์ปฌ ํ…Œ์ŠคํŠธ์—์„œ Django ์„œ๋ฒ„๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜์ง€ ์•Š๋Š” ํ•œ ์ƒ๋‹จ์˜ ํ‘œ์‹œ ์ด๋ฆ„์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฉฐ ์ฒ˜์Œ์—๋งŒ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์— ๋”ฐ๋ฅด๋ฉด ์ด๊ฒƒ์€ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€์— ๋Œ€ํ•œ ์ง€์›์„ ๊ธฐ๊บผ์ด ์ถ”๊ฐ€ํ•˜๋ ค๋Š” ์ฒซ ๋ฒˆ์งธ ์˜ต์…˜ ์ดํ›„์— ๊ฐ€์žฅ ์ข‹์€ ์˜ต์…˜์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

@maxking ๋งˆ์ง€๋ง‰ ์˜ต์…˜์€ ๋งค๋ ฅ์ฒ˜๋Ÿผ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค! ๊ฐ์‚ฌ

ํ•ด๊ฒฐ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

DEFAULT_FROM_DOMAIN ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” ์ด์ œ ๊ธฐ๋ณธ example.com ๋„๋ฉ”์ธ๋„ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์„ค๋ช…์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฉฐ Django ๊ด€๋ฆฌ ์‚ฌ์ดํŠธ์—์„œ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# 95์—์„œ ์ˆ˜์ • ๋จ

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰