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

Hunting For Treasure In Django

C65d18a43152b199ee94aad2b79b70c4?s=47 Seb
May 28, 2015

Hunting For Treasure In Django



May 28, 2015


  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