Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hunting For Treasure In Django

May 28, 2015

Hunting For Treasure In Django


May 28, 2015

More Decks by Seb

Other Decks in Technology


  1. Hunting for Treasure in Django Sebastian Vetter @elbaschid

  2. Who Am I?

  3. Sebastian • Django & Python Developer • Backend Engineer @

    Mobify • github/twitter: elbaschid
  4. What's The Treasure?

  5. Awesome Django Features • Forms, • Views, • Models, •

    the ORM, or • other commonly used APIs.
  6. But They Are Boring

  7. Real Treasure

  8. What Does That Mean? • Useful pieces of Django code.

    • Considered public API. • Documentation is available (sort of). • Mainly used within Django itself.
  9. My Hunting Strategy • Digging through the Django source. •

    Hanging out with Funkybob. • Learning from other great people.
  10. What I'll Do • Show a few "hidden" treasures. •

    Explain what they do. • Look at examples.
  11. cached_property

  12. Where is it useful? • Time or compute heavy properties

    on a class. • Synchronous calls to remote servers. • Used more than once, e.g. code & template.
  13. What does it do? • It's a decorator. • Caches

    the return value. • Lives as long as the instance.
  14. It looks like this class MyObject(object): @cached_property def compute_heavy_method(self): ...

    return result
  15. Imagine A Color API class Color(object): def __init__(self, hex): self.hex

    = hex def _request_colour_name(self, hex): print "Requesting #{}".format(hex) rsp = requests.get(API_ENDPOINT.format(hex)) return rsp.json()[0].get("title") @property def name(self): return self._request_colour_name(self.hex)
  16. Here's the problem • Using the name attribute will call

    the API • Every time!
  17. Here's the problem >>> c = Color('ffffff') >>> c.name Requesting

    #ffffff white >>> c.name Requesting #ffffff white
  18. Possible solution @property def name(self): if self._name is None: self._name

    = self._request_colour_name(self.hex) return self._name
  19. Or you can use cached_property from django.utils.functional import cached_property @cached_property

    def name(self): return self._request_colour_name(self.hex)
  20. Using the cached property >>> c = Color('ffffff') >>> c.name

    Requesting #ffffff white >>> c.name white
  21. Isn't That Great

  22. All you Need To Know from django.utils.functional import cached_property •

    Only cached for the lifetime of the instance. • Be careful with querysets. • Django docs • Source
  23. import_string

  24. Where is it useful? • Make a class or function

    configurable. • Allow loading class/function from string.
  25. What does it do? • Takes dotted path to a

    class or function. • Loads it. • Returns the class or function object.
  26. It looks like this from django.utils.module_loading import import_string get_func =

    import_string('requests.get') print get_func # <function requests.api.get> get_func('https://google.ca') # <Response [200]>
  27. # settings.py UPLOAD_VALIDATION_PIPELINE = [ 'my_project.uploads.validators.is_tarball', 'my_project.uploads.validators.has_readme_file', 'my_project.uploads.validators.has_no_!']

  28. All you Need To Know from django.utils.module_loading import import_string •

    Imports a class or function from a dotted path. • Django docs • Source
  29. lazy and lazy_property

  30. Where is it useful? • Accessing settings at parse time,

    e.g. class attributes. • Translating strings outside of a view. • Translations in the settings module.
  31. Here's a problem class UserSignupView(CreateView): ... success_url = reverse('signup-confirmed')

  32. How can we fix it? from django.utils.functional import lazy class

    UserSignupView(CreateView): ... success_url = lazy(reverse('signup-confirmed'), unicode)
  33. Lazy Django • The Settings object is lazy. • Several

    helpers have lazy siblings: • reverse_lazy • ugettext_lazy • Not sure what lazy_property is useful for.
  34. All you Need To Know from django.utils.functional import lazy from

    django.utils.functional import SimpleLazyObject • Imports a class or function from a dotted path. • Django docs • Source
  35. RequestFactory

  36. Where Is It Useful? • Testing request related code. •

    Mocking will be too much work. • Using the test client doesn't make sense.
  37. Create GET Request from django.test import RequestFactory request = RequestFactory().get('/some/path')

    # with a query string query_params = {"token": "secret-token"} request = RequestFactory().get('/some/path', data=query_params)
  38. Create POST Request from django.test import RequestFactory post_params = {'username':'testuser',

    'password':'supersecret'} request = RequestFactory().post('/login', data=post_params)
  39. All you Need To Know from django.test import RequestFactory •

    Creates a fake request for given URL. • Can handle all HTTP methods. • Will save you some mocking work. • Django docs • Source
  40. The Treasure Is Yours

  41. Thanks! Questions? • www.roadsi.de • @elbaschid • github.com/elbaschid Slides: https://speakerdeck.com/elbaschid