I want to send mails in a cron job. The mail should contain a link to my application.
In cron job, I don't have a request object, and can't use request.build_absolute_uri().
AFAIK the site framework can help here. But does not give me the protocol (http vs https)?
My application is reusable and sometimes gets hosted on http and sometimes on https sites.
Update
I search a common django way. Creating custom settings is possible, but a solution with django standards is preferred.
Use handy request. build_absolute_uri() method on request, pass it the relative url and it'll give you full one. By default, the absolute URL for request. get_full_path() is returned, but you can pass it a relative URL as the first argument to convert it to an absolute URL.
TL;DR: There's no any "standard" "Django-ish" way of doing that, but the DRY principle promoted by the framework assumes the single configuration store, so a custom setting seems to be a good way to go.
By default Django can serve any number of domains from a single instance, and the HTTP request (more accurately, its HTTP_HOST
header) is the only thing Django uses to determine the current host. As your cron jobs are obviously out of the HTTP cycle, you should store your domain somewhere in settings...
# settings.py DEFAULT_DOMAIN = 'https://foobar.com' # or, depending on your configuration: DEFAULT_DOMAIN = 'https://{}'.format(ALLOWED_HOSTS[0])
...with a tiny context processor to make it easier to handle templating:
# yourapp/context_processors.py from django.conf import settings def default_domain(request): return {'default_domain': settings.DEFAULT_DOMAIN}
...and then use it in your emails:
# yourapp/templates/email/body.html <a href="{{ default_domain }}{% url 'target' %}">Click here</a>
Alternatively you can make use of the sites
framework, but if you're serving a single domain, the settings-based solution seems much more simpler and cleaner to me.
There's special standard module for this task - Sites Framework. It adds Site model, which describes specific site. This model has field domain
for domain of the project, and a name
- human-readable name of the site.
You associate your models with sites. Like so:
from django.db import models from django.contrib.sites.models import Site class Article(models.Model): headline = models.CharField(max_length=200) # ... site = models.ForeignKey(Site, on_delete=models.CASCADE)
When you need to make an url for the object you may use something like the following code:
>>> from django.contrib.sites.models import Site >>> obj = MyModel.objects.get(id=3) >>> obj.get_absolute_url() '/mymodel/objects/3/' >>> Site.objects.get_current().domain 'example.com' >>> 'https://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url()) 'https://example.com/mymodel/objects/3/'
This way you can have multiple domains and content spread between them. Even if you have only one domain I recommend use it to achieve a good standard comfortable way to keep domain settings.
Installatioin is quite easy:
Add 'django.contrib.sites'
to your INSTALLED_APPS
setting.
Define a SITE_ID setting:
SITE_ID = 1
Run migrate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With