Django community: RSS
This page, updated regularly, aggregates Community blog posts from the Django community.
-
Populate Your Test Database With Mixins
While Django has support for loading fixtures in its unit testing tools, I have found that maintaining fixtures over time is nothing less than a giant pain in the butt. As your model definitions change over time, remembering to re-run manage.py dumpdata myapp >fixtures.json any time your fixtures are affected is something I guarantee you will forget to do. Not to mention the fact that your database may or may not contain records suitable for testing at any given time. Then all of your unit tests have blown up, it takes you a little bit of time to figure out why, and before you know it you are cursing and out of your flow. For a time I tried using Alex Gaynor's django-fixture-generator but that only solved the problem of creating the records you want to test, not the problem of fixtures sitting on disk that are out of sync with your model schema. After being introduced to Django class-based views' mixin-heavy style, I cooked up a technique for unit test TestCase classes to create the records they need at runtime, thus bypassing the need for fixtures. In an apps tests/__init__.py I create a PopulateDbMixin: class PopulateDbMixin(object): def populate_db(self): """Assume … -
Populate Your Test Database With Mixins
While Django has support for loading fixtures in its unit testing tools, I have found that maintaining fixtures over time is nothing less than a giant pain in the butt. As your model definitions change over time, remembering to re-run manage.py dumpdata myapp >fixtures.json any time your fixtures are affected is something I guarantee you will forget to do. Not to mention the fact that your database may or may not contain records suitable for testing at any given time. Then all of your unit tests have blown up, it takes you a little bit of time to figure out why, and before you know it you are cursing and out of your flow. For a time I tried using Alex Gaynor's django-fixture-generator but that only solved the problem of creating the records you want to test, not the problem of fixtures sitting on disk that are out of sync with your model schema. After being introduced to Django class-based views' mixin-heavy style, I cooked up a technique for unit test TestCase classes to create the records they need at runtime, thus bypassing the need for fixtures. In an apps tests/__init__.py I create a PopulateDbMixin: class PopulateDbMixin(object): def populate_db(self): """Assume … -
Email Validation
Email validation has always been a bit of a nightmare. On the one hand there are all of the local domain names (sometimes even a single word can be a valid email) meanwhile there is an explosion of top level domain names confusing the entire internet for no reason I've been able to work out.Anyway my problem today is that my payment processor SagePay validates emails and will decline the transaction if the email validation fails. I am using Django's EmailField to validate the addresses but unfortunately SagePay and Django have different views on what is a valid email with SagePay being more strict.In a fit of optimism I emailed SagePay support to try to find out the algorithm, after a brief exchange of mails I got to it as "RFC532n" which completely mystified me (and Google!) However on reading their documentation I got referred to RFC3696 which made more sense although it is one of the RFC's which leaves things quite open with a lot of advice rather than firm rules. So I did a bit of testing to try to reverse engineer the SagePay algorithm and it looks like it is the Django algorithm with the addition of … -
Mercurial Mirror For Django 1.7 Branch
Today the Django project released the first alpha for Django 1.7. As such, the branch for 1.7 has been created in the git repository, and we can start mirroring it. Of course, this is still an alpha and the clone shouldn’t be used yet for prodution. The purpose is to test 1.7 early and to […] -
awesome-slugify: Human-readable URL slugs from any string (part 2)
In my previous blog post I covered using awesome-slugify to capture slugs in both ASCII and unicode. Today I'm covering the definition custom language slugify translation functions. Defining Custom Language slugify Translation Functions For those times we need ASCII representation of unicode characters, we can't always use the default unicode-to-ASCII mappings. A powerful feature of awesome-slugify is we can quickly and easily create our own translation functions. Just follow these two steps: Define a translation dictionary. Keys are the names of things you want translated, and the associated values are what the keys are translated into. Generate a translation function using slugify.main.get_slugify(). Explaining this in depth will take paragraphs of text, so I'll just demonstrate it using emoji: # -*- coding: utf-8 -*- # test_slugify_emoji.py from slugify import get_slugify import pytest # Step 1: Define the translation dictionary ALT_EMOJI = { u'ʘ‿ʘ': u'smiling', u'ಠ_ಠ': u'disapproval', u'♥‿♥': u'enamored', u'♥': u'love', } # Step 2: Generate a translation function slugify_emoji = get_slugify(pretranslate=ALT_EMOJI) def test_basic_emoji(): assert slugify_emoji(u"ʘ‿ʘ") == u"smiling" assert slugify_emoji(u"ಠ_ಠ") == u"disapproval" def test_sentence(): txt = u"I ♥ Audrey Roy Greenfeld" assert slugify_emoji(txt) == u"I-love-Audrey-Roy-Greenfeld" if __name__ == "__main__": pytest.main() More Practical Applications While writing an emoji-based translation function is fun, most … -
awesome-slugify: Human-readable URL slugs from any string (part 2)
In my previous blog post I covered using awesome-slugify to capture slugs in both ASCII and unicode. Today I'm covering the definition custom language slugify translation functions. Defining Custom Language slugify Translation Functions For those times we need ASCII representation of unicode characters, we can't always use the default unicode-to-ASCII mappings. A powerful feature of awesome-slugify is we can quickly and easily create our own translation functions. Just follow these two steps: Define a translation dictionary. Keys are the names of things you want translated, and the associated values are what the keys are translated into. Generate a translation function using slugify.main.get_slugify(). Explaining this in depth will take paragraphs of text, so I'll just demonstrate it using emoji: # -*- coding: utf-8 -*- # test_slugify_emoji.py # The way the awesome-slugify API works, you can't directly import from # the 'slugify' package. You have to import from the 'slugify.main' # module. See https://github.com/dimka665/awesome-slugify/issues/2 from slugify.main import get_slugify import pytest # Step 1: Define the translation dictionary ALT_EMOJI = { u'ʘ‿ʘ': u'smiling', u'ಠ_ಠ': u'disapproval', u'♥‿♥': u'enamored', u'♥': u'love', } # Step 2: Generate a translation function slugify_emoji = get_slugify(pretranslate=ALT_EMOJI) def test_basic_emoji(): # awesome-slugify capitalizes strings. # see https://github.com/dimka665/awesome-slugify/issues/3 assert slugify_emoji(u"ʘ‿ʘ") == u"Smiling" … -
awesome-slugify: Human-readable URL slugs from any string
note: The introduction mentions Django and Plone. However, this is not an article about Django or Plone. Introduction Years ago, when I was working with Plone at NASA, one thing I dreaded was when content editors would copy-and-paste from Microsoft Word into the title bar. All kinds of funny characters would appear in the title bar and URL. I would have to go into the database (ZODB) and fix things. Things didn't get better until Reed O'Brien turned on a title validator (probably in Plone.i18n). When we started using Django, one thing that made it nice was the presence of it's slugify() function and template filter. Inspired by the newspaper industry, this function it easier on both content editors and software engineers. In any case, using slugify() we completed a number of projects, with NASA Science being the only public one I worked on. As much as the slugify() function was useful, there were problems. As I discovered time and time again over the years, it didn't handle unicode. Or rather, it handled them by simply vanishing non-ASCII unicode characters. For example: >>> from django.utils.text import slugify >>> slugify(u"straße") # German for road u"strae" If you read German, you'll know … -
awesome-slugify: Human-readable URL slugs from any string
note: The introduction mentions Django and Plone. However, this is not an article about Django or Plone. Introduction Years ago, when I was working with Plone at NASA, one thing I dreaded was when content editors would copy-and-paste from Microsoft Word into the title bar. All kinds of funny characters would appear in the title bar and URL. I would have to go into the database (ZODB) and fix things. Things didn't get better until Reed O'Brien turned on a title validator (probably in Plone.i18n). When we started using Django, one thing that made it nice was the presence of it's slugify() function and template filter. Inspired by the newspaper industry, this function it easier on both content editors and software engineers. In any case, using slugify() we completed a number of projects, with NASA Science being the only public one I worked on. As much as the slugify() function was useful, there were problems. As I discovered time and time again over the years, it didn't handle unicode. Or rather, it handled them by simply vanishing non-ASCII unicode characters. For example: >>> from django.utils.text import slugify >>> slugify(u"straße") # German for road u"strae" If you read German, you'll know … -
Django Extensions 1.3.3
We are proud to release: Django-Extensions Version 1.3.3 This brings the usual tons of fixes and improvements Get it now: https://pypi.python.org/pypi/django-extensions/1.3.3 Changelog: Docs: Made it clearer that Django Extensions requires Django 1.4 or higher Translations: FR Updated Python3: Fix for shell_plus -
awesome-slugify: Human-readable URL slugs from any string
Years ago, when I was working with Plone at NASA, one thing I dreaded was when content editors would copy-and-paste from Microsoft Word into the title bar. All kinds of funny characters would appear in the title bar and URL. I would have to go into the database (ZODB) and fix things. Things didn't get better until Reed O'Brien turned on a title validator (probably in Plone.i18n). When we started using Django, one thing that made it nice was the presence of it's slugify() function and template filter. Inspired by the newspaper industry, this function it easier on both content editors and software engineers. In any case, using slugify() we completed a number of projects, with NASA Science being the only public one I worked on. As much as the slugify() function was useful, there were problems. As I discovered time and time again over the years, it didn't handle unicode. Or rather, it handled them by simply vanishing non-ASCII unicode characters. For example: >>> from django.utils.text import slugify >>> slugify(u"straße") # German for road u"strae" If you read German, you'll know that the default Django slugify() function is converting the word 'road' to nonsense. For sites dealing with internationalization, … -
ViewSets and Routers - django-rest-framework part 3
ViewSets and Routers are very useful for slimming up your code and providing a lot of default functionality out of the box. They are powerful features in django-rest-framework allowing a lot of flexibility in your code while keeping things clean.Watch Now... -
Django Best Practices -Django开发的最佳实践
推荐一篇Django的开发及部署的文章:Django Best Practices--A guide to d […] -
Just Married, and Proof #1 Is In
Happy 2014! We have a couple of exciting announcements: First, in case you haven't heard, Daniel and I just got married. It's not every day that co-authors of Django books get married, right? Here was our wedding cartwheel. Photo credit: Lindy DiMaio - Della Vita Photography. Second, the first print proof of Two Scoops of Django 1.6 arrived in the mail this week. Goodness, it is heavy! Here's how it compares to the 1.5 edition: Note that the final version may look drastically different -- right now we are tweaking colors and making lots of edits. In fact, it will still take several iterations before the book is ready. It may even take months. But hopefully not. Hopefully it'll be more like weeks. -
Just Married, and Proof #1 Is In
Happy 2014! We have a couple of exciting announcements: First, in case you haven't heard, Daniel and I just got married. It's not every day that co-authors of Django books get married, right? Here was our wedding cartwheel. Photo credit: Lindy DiMaio - Della Vita Photography. Second, the first print proof of Two Scoops of Django 1.6 arrived in the mail this week. Goodness, it is heavy! Here's how it compares to the 1.5 edition: Note that the final version may look drastically different -- right now we are tweaking colors and making lots of edits. In fact, it will still take several iterations before the book is ready. It may even take months. But hopefully not. Hopefully it'll be more like weeks. -
Just Married, and Proof #1 Is In
Happy 2014! We have a couple of exciting announcements: First, in case you haven't heard, Daniel and I just got married. It's not every day that co-authors of Django books get married, right? Here was our wedding cartwheel. Photo credit: Lindy DiMaio - Della Vita Photography. Second, the first print proof of Two Scoops of Django 1.6 arrived in the mail this week. Goodness, it is heavy! Here's how it compares to the 1.5 edition: Note that the final version may look drastically different -- right now we are tweaking colors and making lots of edits. In fact, it will still take several iterations before the book is ready. It may even take months. But hopefully not. Hopefully it'll be more like weeks. -
pytest: no-boilerplate testing (part 3)
In my previous blog post I covered writing exception-based assertions and fixtures. Today I'm going to close things out by demonstrating how to change the behavior of pytest and how to integrate it with Django and setup.py. Changing the Behavior of pytest When pytest is called, either via the command-line or by pytest.main(), it looks for a configuration file called either pytest.ini, tox.ini, and setup.cfg. If it finds a configuration file, it follows standard practices for those things. In the following example, I demonstrating searching for tests inside of all Python files while ignoring the _build directories: # pytest.ini (or tox.ini or setup.cfg) [pytest] # You must put pytest-related controls in a 'pytest' block python_files=*.py # Run tests against all python modules norecursedirs = _build # Don't look inside of _build directories Changing pytest Behavior Dynamically This is pretty nice, but if I need to ignore certain Python modules like setup.py? I can do this by creating a conftest.py module and defining a collect_ignore variable. # conftest.py collect_ignore = ["setup.py", "conftest.py"] The conftest.py module can actually be defined per directory. So if test behavior needs to change in different packages, just create additional conftest.py modules. It's simple to do, but … -
pytest: no-boilerplate testing (part 3)
-
pytest: no-boilerplate testing (part 2)
In my previous blog post I covered test discovery and writing basic tests using pytest. Today I'm going to cover a few more features that I really enjoy: raises and fixtures. The Intuitively Named raises context manager When using pytest, you can assert whether or not an exception occurred via the following: # test_exceptions.py from pytest import raises def test_an_exception(): with raises(IndexError): # Indexing the 30th item in a 3 item list [5, 10, 15][30] Fixtures as Function Arguments When writing tests, it's not uncommon to need common objects used between tests. However, if you have a complicated process to generate these common objects, then you have to write tests for your tests. When using Python's venerable unittest framework, this always causes a spaghetti-code headache. However, via the virtue of simplicity, pytest helps keep our test code cleaner and more maintainable. Rather than try and explain that further, I'll write some code to get my point across: # test_fixtures.py from pytest import fixture @fixture # Registering this function as a fixture. def complex_data(): # Creating test data entirely in this function to isolate it # from the rest of this module. class DataTypes(object): string = str list = list return … -
pytest: no-boilerplate testing (part 2)
In my previous blog post I covered test discovery and writing basic tests using pytest. Today I'm going to cover a few more features that I really enjoy: raises and fixtures. The Intuitively Named raises context manager When using pytest, you can assert whether or not an exception occurred via the following: # test_exceptions.py from pytest import raises def test_an_exception(): with raises(IndexError): # Indexing the 30th item in a 3 item list [5, 10, 15][30] class CustomException(Exception): pass def test_my_exception(): with raises(CustomException): raise CustomException This is similar to, but just a bit easier to remember than the implementation in unittest. What I like about it is that even if I step away from code and tests for enough time to go on vacation and get married, when I come back I always remember the precise name of the context manager used to raise exceptions. Fixtures as Function Arguments When writing tests, it's not uncommon to need common objects used between tests. However, if you have a complicated process to generate these common objects, then you have to write tests for your tests. When using Python's venerable unittest framework, this always causes a spaghetti-code headache. However, via the virtue of simplicity, … -
Sending emails with embedded images in Django
Django offers useful classes to easily send email. It is also easy to add attachments to emails. I did have to puzzle a bit to get embedded images working. This article describes the way I do it now. I will first describe the most important elements and then I will show a more complete example. The elements Since I send a plain text and HTML version of the email, I use the EmailMultiAlternatives class: msg = EmailMultiAlternatives(subject, text_content, sender, [to_mail]) The images are included as attachments. We do not use the attach_file method because we want to set the Content-ID header. This way we can refer to the image by that ID in the template. for f in ['logo.png', 'logo-footer.png']: fp = open(os.path.join(os.path.dirname(__file__), f), 'rb') msg_img = MIMEImage(fp.read()) fp.close() msg_img.add_header('Content-ID', '<{}>'.format(f)) msg.attach(msg_img) As far as I have seen, the images can only actually be included if the content type of the mail is correctly set. By default, the content type is set to “multipart/alternative”. But this resulted in the images just being displayed as attachments. What I needed was to set the content type to “multipart/related”: msg.mixed_subtype = 'related' (This is the thing that took the most time to figure … -
pytest: no-boilerplate testing
When I first encountered Holger Krekel's pytest this summer on Jeff Knupp's blog I felt like I had been living under a rock for years. I've been using Python's unittest framework since 2006 and nose to find tests since 2008, but here was another test framework dating back to at least January 24, 2007. pytest is a very mature testing tool for testing Python. My favorite features: It can run unittest, doctest, and nose, style tests suites, making it ideal for new and legacy projects. It includes an intuitively named raises context manager for testing exceptions. You can define fixture arguments to generate baseline data. This is very, very different from Django-style fixtures. Via pytest.ini you can change the behavior of pytest. Integrates nicely with setup.py. Alright, lets dive into usage. Test Discovery The first thing that pytest provides is test discovery. Like nose, starting from the directory where it is run, it will find any Python module prefixed with test_ and will attempt to run any defined unittest or function prefixed with test_. pytest explores properly defined Python packages, searching recursively through directories that include __init.py__ modules. Since an image is probably easier to read, here's a sample directory … -
pytest: no-boilerplate testing
When I first encountered Holger Krekel's pytest this summer on Jeff Knupp's blog I felt like I had been living under a rock for years. I've been using Python's unittest framework since 2006 and nose to find tests since 2008, but here was another test framework that actually predates nose! pytest is a very mature testing tool for testing Python. My favorite features: It can run unittest, doctest, and nose, style tests suites, making it ideal for new and legacy projects. It includes an intuitively named raises context manager for testing exceptions. You can define fixture arguments to generate baseline data. This is very, very different from Django-style fixtures. Via pytest.ini you can change the behavior of pytest. Integrates nicely with setup.py. Alright, lets dive into usage. Test Discovery The first thing that pytest provides is test discovery. Like nose, starting from the directory where it is run, it will find any Python module prefixed with test_ and will attempt to run any defined unittest or function prefixed with test_. pytest explores properly defined Python packages, searching recursively through directories that include __init__.py modules. Since an image is probably easier to read, here's a sample directory structure annotated with which … -
Retiring as BDFLs
Adrian broke the news: today, he and I are retiring as BDFLs, transitioning to a truly community-run project. Adrian wrote a bit about the history of the BDFL term and our roles wearing that hat. Go check out his writing for that, and for some of his personal thoughts. Here, I’ll just add a few things of my own: For me, this has been a long time coming – I’ve been thinking about this for at least a year. -
Managing Events with Explicit Time Zones
Recently we wanted a way to let users create real-life events which could occur in any time zone that the user desired. By default, Django interprets any date/time that the user enters as being in the user’s time zone, but it never displays that time zone, and it converts the time zone to UTC before storing it, so there is no record of what time zone the user initially chose. This is fine for most purposes, but if you want to specifically give the user the ability to choose different time zones for different events, this won’t work. One idea I had was to create a custom model field type. It would store both the date/time (in UTC) and the preferred time zone in the database, and provide a form field and some kind of compound widget to let the user set and see the date/time with its proper time zone. We ended up with a simpler solution. It hinged on considering the time zone separately from a time. In our case, we would set a time zone for an event. Any date/time fields in that event form would then be interpreted to be in that time zone. Now, displaying … -
Managing Events with Explicit Time Zones
Managing Events with Explicit Time Zones Recently we wanted a way to let users create real-life events which could occur in any time zone that the user desired. By default, Django interprets any date/time that the user enters as being in the user’s time zone, but it never displays that time zone, and it converts the time zone to UTC before storing it, so there is no record of what time zone the user initially chose. This is fine for most purposes, but if you want to specifically give the user the ability to choose different time zones for different events, this won’t work.