sunscrapers / django-templated-mail

Send emails using Django template system.
MIT License
95 stars 22 forks source link

ability to disable get_current_site #11

Open theromis opened 5 years ago

theromis commented 5 years ago

getting issue because have to use restful api by IP, in some countries my domain is not resolvable (don't know why) when requested by IP getting this backtrace:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/exception.py", line 35, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py", line 128, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py", line 126, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.6/dist-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/django/views/generic/base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py", line 483, in dispatch
    response = self.handle_exception(exc)
  File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py", line 443, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py", line 480, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/djoser/utils.py", line 33, in post
    return self._action(serializer)
  File "/usr/lib/python3/dist-packages/djoser/views.py", line 133, in _action
    self.send_password_reset_email(user)
  File "/usr/lib/python3/dist-packages/djoser/views.py", line 150, in send_password_reset_email
    settings.EMAIL.password_reset(self.request, context).send(to)
  File "/usr/local/lib/python3.6/dist-packages/templated_mail/mail.py", line 68, in send
    self.render()
  File "/usr/local/lib/python3.6/dist-packages/templated_mail/mail.py", line 60, in render
    context = make_context(self.get_context_data(), request=self.request)
  File "/usr/lib/python3/dist-packages/djoser/email.py", line 30, in get_context_data
    context = super(PasswordResetEmail, self).get_context_data()
  File "/usr/local/lib/python3.6/dist-packages/templated_mail/mail.py", line 32, in get_context_data
    site = get_current_site(self.request)
  File "/usr/local/lib/python3.6/dist-packages/django/contrib/sites/shortcuts.py", line 13, in get_current_site
    return Site.objects.get_current(request)
  File "/usr/local/lib/python3.6/dist-packages/django/contrib/sites/models.py", line 62, in get_current
    return self._get_site_by_request(request)
  File "/usr/local/lib/python3.6/dist-packages/django/contrib/sites/models.py", line 47, in _get_site_by_request
    SITE_CACHE[domain] = self.get(domain__iexact=domain)
  File "/usr/local/lib/python3.6/dist-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/django/db/models/query.py", line 403, in get
    self.model._meta.object_name
django.contrib.sites.models.DoesNotExist: Site matching query does not exist.

I think at least wrap it in try should be useful feature

hawi74 commented 5 years ago

I think this is not a problem with django-templated-mail, but rather with your django.contrib.sites configuration. Did you provide SITE_ID in your project settings?

theromis commented 5 years ago

@hawi74 SITE_ID was disabled because I'm processing multiple domains with this snippet https://stackoverflow.com/questions/25681883/django-multiple-domains-single-app

class MultiSiteMiddleware(object):

    def process_request(self, request):
        try:
            domain = request.get_host().split(":")[0]
            request.site = Site.objects.get(domain=domain)
        except Site.DoesNotExist:
            return http.HttpResponseNotFound()
hawi74 commented 5 years ago

@theromis this is probably because you are stripping the port while Django's get_current_site function never does it. I highly recommend that you use this function as well, instead of directly accessing Site model. You will also have to include the port in your Site instance. Please let me know if that helps.

theromis commented 5 years ago

@hawi74 Sorry for posting wrong code snippet, here is my actual code used in project:

cat multihost.py
"""

 A simple middleware component that lets you use a single Django
 instance to server multiple distinct hosts.

 IMPORTANT!! Make sure this is the FIRST entry in your MIDDLEWARE_CLASSES

 Revision log:

 v1.2 - 10th January 2012 (Cal Leeming - cal.leeming@simplicitymedialtd.co.uk)
  * Added 'LoadingTime' response header (tells us how long the request took to process)
  * Added 'MultiHost' response header (tells us if multihost was used or not)
  * Added 'HOST_MIDDLEWARE_URLCONF_MAP' example
  * Cleaned up code slightly

https://code.djangoproject.com/wiki/MultiHostMiddleware
# File: settings.py

HOST_MIDDLEWARE_URLCONF_MAP = {
    # Control Panel
    "www.example.com": "webapp.sites.example.urls",
}
"""

import time
from django.conf import settings
from django.utils.cache import patch_vary_headers

class MultiHostMiddleware:

    def process_request(self, request):
        try:
            request.META["LoadingStart"] = time.time()
            host = request.get_host()
            #if host[-3:] == ":80":
            #    host = host[:-3] # ignore default port number, if present

            # best way to do this.
            host_port = host.split(':')
            if len(host_port)==2:
                host = host_port[0]

            if host in settings.HOST_MIDDLEWARE_URLCONF_MAP:
                request.urlconf = settings.HOST_MIDDLEWARE_URLCONF_MAP[host]
                request.META["MultiHost"] = str(request.urlconf)
            else:
                request.META["MultiHost"] = str(settings.ROOT_URLCONF)

        except KeyError:
            pass # use default urlconf (settings.ROOT_URLCONF)

    def process_response(self, request, response):
        return response
        if 'MultiHost' in request.META:
            response['MultiHost'] = request.META.get("MultiHost")

        if 'LoadingStart' in request.META:
            _loading_time = time.time() - int(request.META["LoadingStart"])
            response['LoadingTime'] = "%.2fs" % ( _loading_time, )

        if getattr(request, "urlconf", None):
            patch_vary_headers(response, ('Host',))
        return response
hawi74 commented 5 years ago

@theromis are you running a single Django app instance that handles multiple domains or separate instance for each domain? Have you tried creating a Site instance for the domain that causes the issue?

theromis commented 5 years ago

@hawi74 Yes, it handles about 4 different domains and it have them in sites db. rest of it in this snippet, I need different domains to handle different localizations as well.