{ "info": { "author": "Martin Brochhaus", "author_email": "mbrochh@gmail.com", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 2.2", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.6", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content" ], "description": "# Django Email Testview\n\nThis is a highly opinionated little helper tool that helps us at The Artling to\ntest our email templates. It is quite possible that you will not be able to use\nthis in your project because it would require you to refactor tons of your code,\nwhich might not be worth the effort.\n\nHowever, you could always add this app to your project and then just use it for\nnew email templates and you can gradually migrate old emails to this new\nframework over time.\n\n## The problem\n\nOur app sends tons of different email notifications to our users and our admins.\nIn the worst situation, a developer would click around in the frontend until\nthey reach the point where a certain email would be triggered. Then keep\nrefreshing GMail until the email arrives, look at it, then make a few changes,\nthen trigger it again. This is an incredibly frustrating and time consuming\nworkflow.\n\n## The solution\n\nWe would like to have one view `/emails/test/` which can only be accessed by\nadmins and which shows a list of all emails that are registered in the system.\nWhen you click at one of those links, it should show a view that simply renders\nthat email template in the browser.\n\nThe only tricky part with this is that most emails need quite complicated\ntemplate contexts in order to render all the stuff that should be shown in the\nemail. It would be nice if this \"email testview\" would not just render the\ntemplate with fixture values, but even call the real function that prepares the\nemail context, so that this view would crash in the case when there are bugs in\nthat function.\n\n## The opinionated approach\n\nWith this app, you will create your emails as follows:\n\n### Step 1: Create your email template\n\nLet's say you have an app called `contact`. First, you will create the email\ntemplates in that app:\n\n```\ncontact\n \u2514\u2500\u2500 templates\n \u2514\u2500\u2500 contact\n \u2514\u2500\u2500 email\n \u251c\u2500\u2500 body\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 new_contact_request.html\n \u2514\u2500\u2500 subject\n \u2514\u2500\u2500 new_contact_request.html\n```\n\nBy convention, the files for the email `body` and the email `subject` must have\nan identical name and they must be located in an\n`appname/templates/appname/email/` folder .\n\n### Step 2: Create your email function\n\nJust like many Django apps have a `models.py` or an `admin.py`, you will now\nadd an `emails.py` to your app. It will look something like this:\n\n```py\nfrom email_testview.registry import registry\n\n\ndef new_contact_email_fixtures():\n return ['Test message'], {'first_name': 'First', 'last_name': 'Last'}\n\n\ndef new_contact_email(message, first_name=None, last_name=None):\n return {\n 'context': {\n 'message': message,\n 'first_name': first_name,\n 'last_name': last_name,\n },\n # These are optional:\n # 'from_email': 'someone@example.com', # default: settings.FROM_EMAIL\n # 'recipients': ['someone@example.com'], # default: the first from settings.ADMINS\n }\n\n\nregistry.register('contact.new_contact_email', new_contact_email, new_contact_email_fixtures)\n```\n\nYou can see that writing an email consists of three parts:\n\n1. First you write your actual email function (here: `new_contact_email()`).\n Your email function will probably take in some arguments, usually some\n instance from your database or other values that should be rendered in the\n email. This function simply returns the context that shall be passed into the\n email template.\n2. Next you write a fixtures function that will return exactly the `*args` and\n `**kwargs` that your email function needs. We use tools like `mixer` here\n (with `commit=False`) in order to create complex object structures (like a\n user's cart with cart items and all that) with just a few lines of code.\n3. Finally you register this email to a central registry, similar how you would\n also register your Django admin classes.\n\n**Why do we like this?**\n\nThe nice thing about all this is that whenever someone needs to design a new\nemail, they will probably look into an already existing `emails.py` and quickly\nunderstand this three-step-pattern, then copy and paste one old email and just\nchange around all the values as needed. Also, whenever you need to change the\ncontext for an old email, you will have the corresponding fixtures function\nright above it and you will remember that you might have to change the fixtures\nas well.\n\nAnother cool thing is, that in both cases, when the server actually sends an\nemail and when the developer looks at the email in the `/emails/test/` view, the\nexact same email function will be called, so if there are bugs in that email\nfunction, it is more likely that the developer is going to see them while\ndesigning the email.\n\n### Step 3: Send your email\n\nThis app comes with a `send_mail` function that you can use like this:\n\n```py\nfrom email_testview.utils import send_mail\n\nmessage = 'Some message'\nfirst_name = 'First'\nlast_name = 'Last'\nsend_mail('contact.new_contact_email', message, first_name=first_name, last_name=last_name)\n```\n\nThe `send_mail` function will pass the given `*args` and `**kwargs` into your\nemail function `new_contact_email()`. It will then look at the email identifier\nthat you have given (`contact.new_contact_email`) and figure out the template\nname.\n\nThis means: Your email function name and the template name must be identical!\n\n### Step 4: Profit\n\nYou can now login as an admin, go to `/emails/test/` click at the email that you\nwant to modify, see the email in your browser and start modifying the html and\nthe css and see the results in your browser immediately.\n\n# Installation\n\nInstall via pip:\n\n```\npip install django-email-testview\n```\n\nAdd to your `INSTALLED_APPS` settings:\n\n```py\nINSTALLED_APPS = [\n # ...\n 'email_testview',\n]\n```\n\nAdd to your main `urls.py`:\n\n```py\nurlpatterns = [\n re_path(r'admin/', admin.site.urls),\n # ...\n re_path(r'emails/', include('email_testview.urls')),\n]\n```\n\nAdd to your `local_settings.py`:\n\n```py\nENVIRONMENT = 'local'\n```\n\nThis is just another safeguard to make sure that this view can never be accessed\non a production environment. Our production environments have this setting set\nto `prod` and when that is the case, then the view will return a 403 error..\n\nCreate an `emails.py` file in one of your apps, as described above. Make sure\nthat you are logged in as an admin user and visit `/emails/test/`.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/theartling/django-email-testview/", "keywords": "", "license": "MIT License", "maintainer": "", "maintainer_email": "", "name": "django-email-testview", "package_url": "https://pypi.org/project/django-email-testview/", "platform": "", "project_url": "https://pypi.org/project/django-email-testview/", "project_urls": { "Homepage": "https://github.com/theartling/django-email-testview/" }, "release_url": "https://pypi.org/project/django-email-testview/0.1.0/", "requires_dist": [ "Django (==2.2.2)", "pytest; extra == 'dev'", "pytest-django; extra == 'dev'", "pytest-cov; extra == 'dev'", "fabric; extra == 'dev'", "mixer; extra == 'dev'" ], "requires_python": "", "summary": "Strongly opinionated way to handle emails with Django", "version": "0.1.0" }, "last_serial": 5922185, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "51ffca6fb6c32fb7d66d833f8f8b0f06", "sha256": "b18fb95f95f7076bc4e82c87ced092ad9889f42d2c49ee16c1935bbf83198c32" }, "downloads": -1, "filename": "django_email_testview-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "51ffca6fb6c32fb7d66d833f8f8b0f06", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6044, "upload_time": "2019-06-14T09:23:18", "url": "https://files.pythonhosted.org/packages/ab/94/fa688ba359591636ddfe9c17c1a7bdede8b2a5e34438adc43ec8658a71a4/django_email_testview-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "98aa90fbdafbb84f3a3f55d4946212b1", "sha256": "610b438efd73bda05ff96181fb01aa7ccf2a6bf8118f2752beb9243a8411b3fd" }, "downloads": -1, "filename": "django-email-testview-0.0.1.tar.gz", "has_sig": false, "md5_digest": "98aa90fbdafbb84f3a3f55d4946212b1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6217, "upload_time": "2019-06-14T09:23:21", "url": "https://files.pythonhosted.org/packages/b1/20/15dd6feb33e7164c3e2326862865b20e87687c720bafddcf5158834aef7f/django-email-testview-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "15749997d74df20726b5341703a2e0cb", "sha256": "d2f22a456f94496d65da685479993c20d9bb152de3334adea34affc1ece62f93" }, "downloads": -1, "filename": "django_email_testview-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "15749997d74df20726b5341703a2e0cb", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6896, "upload_time": "2019-06-14T09:33:08", "url": "https://files.pythonhosted.org/packages/b2/5b/6478ac14e077487b922ab1739dc3bfa64edfcf153775aa12663941f9ac99/django_email_testview-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1910d2f9fb6cb3d486862b9b87ee0cc5", "sha256": "b7f48b4cc125b8686455869af5c8c6e05f4af8bc0170a342de99893f5a44a52e" }, "downloads": -1, "filename": "django-email-testview-0.0.2.tar.gz", "has_sig": false, "md5_digest": "1910d2f9fb6cb3d486862b9b87ee0cc5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6210, "upload_time": "2019-06-14T09:33:10", "url": "https://files.pythonhosted.org/packages/5c/ab/563b227853db64e73bfb930d23266d3611864e0f2ec57849cc06c73b5736/django-email-testview-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "565b29f3255b57f7c4a142767e680194", "sha256": "2b55915094845f1656314ebac72eea1642946845e1b15b41015dab3ae85246ef" }, "downloads": -1, "filename": "django_email_testview-0.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "565b29f3255b57f7c4a142767e680194", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7234, "upload_time": "2019-06-14T10:04:50", "url": "https://files.pythonhosted.org/packages/ea/f4/9cc43fd468285a04d6a668cd07bc8e72bdde15411533b30c46b1b6cae2a3/django_email_testview-0.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2c4e9efd3cc18199a31175692e5c108f", "sha256": "62e9897bdf53f496d08fdc35b36ad28259fe87431641d8f96f1373d7eb001453" }, "downloads": -1, "filename": "django-email-testview-0.0.3.tar.gz", "has_sig": false, "md5_digest": "2c4e9efd3cc18199a31175692e5c108f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6378, "upload_time": "2019-06-14T10:04:51", "url": "https://files.pythonhosted.org/packages/1b/53/c7ce6f7741b04ec3ab74fa852d068650d75c97f5fc78202d643d05743009/django-email-testview-0.0.3.tar.gz" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "5a9e2b0bfd7363c3bbc641f6f5506fd3", "sha256": "d1abe60c310eb49fefa62cbc4178c84b86dec3c653cd8e640e82baad80ab238e" }, "downloads": -1, "filename": "django_email_testview-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "5a9e2b0bfd7363c3bbc641f6f5506fd3", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6769, "upload_time": "2019-10-03T07:45:15", "url": "https://files.pythonhosted.org/packages/5f/dd/da163693cf81372badd0e3c8e1b765018433c3403a3fc73a961fe3fd49c1/django_email_testview-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "df1710bad60254d90872a38dc5503fe5", "sha256": "6f40b202f64190f54f61e0c82912afc6e810047269a493f5f2702dd913e36340" }, "downloads": -1, "filename": "django-email-testview-0.1.0.tar.gz", "has_sig": false, "md5_digest": "df1710bad60254d90872a38dc5503fe5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7596, "upload_time": "2019-10-03T07:45:17", "url": "https://files.pythonhosted.org/packages/a0/59/76c1e9972b8160280d138d8cf0544ecd285d2ec7244e3471bba523cee986/django-email-testview-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "5a9e2b0bfd7363c3bbc641f6f5506fd3", "sha256": "d1abe60c310eb49fefa62cbc4178c84b86dec3c653cd8e640e82baad80ab238e" }, "downloads": -1, "filename": "django_email_testview-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "5a9e2b0bfd7363c3bbc641f6f5506fd3", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6769, "upload_time": "2019-10-03T07:45:15", "url": "https://files.pythonhosted.org/packages/5f/dd/da163693cf81372badd0e3c8e1b765018433c3403a3fc73a961fe3fd49c1/django_email_testview-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "df1710bad60254d90872a38dc5503fe5", "sha256": "6f40b202f64190f54f61e0c82912afc6e810047269a493f5f2702dd913e36340" }, "downloads": -1, "filename": "django-email-testview-0.1.0.tar.gz", "has_sig": false, "md5_digest": "df1710bad60254d90872a38dc5503fe5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7596, "upload_time": "2019-10-03T07:45:17", "url": "https://files.pythonhosted.org/packages/a0/59/76c1e9972b8160280d138d8cf0544ecd285d2ec7244e3471bba523cee986/django-email-testview-0.1.0.tar.gz" } ] }