Re: Logging format decision
On Jan 14, 1:57 am, Russell Keith-Mageewrote: > The other issue that I think still needs to be addressed is the > internal usage of logging by Django itself. My biggest hangup with the logging implementation was figuring out exactly when the logging configuration code should actually run. The problem is that Django's startup execution order is poorly defined - stuff relating to settings is lazily evaluated the first time it's needed, and there's no real documented place to put code that needs to be executed once (the fact so many registration things end up being called from urls.py is a good indicator that this is a problem). This has put me off using signal handlers in my own code in the past, and it also came up with the logging work. I think Django needs a defined and documented execution order on startup. I'm not entirely clear why we've avoided this in the past - I've read http://www.b-list.org/weblog/2007/nov/05/server-startup/ but it hasn't convinced me that a defined startup order for things like registration patterns, signal handlers, logging configuration is a bad thing. Personally, I'd like to see this happen as part of the instantiation of a single Django "site object" which handles all requests to the server. We almost do this at the moment - if you look at the code in http://code.djangoproject.com/browser/django/trunk/django/core/handlers/ each handler basically instantiates an object once which then has its get_response() method called for every incoming request. Unfortunately the time at which this object is instantiated seems to be pretty ad- hoc - how and when it happens depends on if you're running under WSGI, mod_python or the development server. Defining Django's execution order is a pretty big job, but it would be a great thing to achieve for 1.3. The obvious thing to tie it to would be INSTALLED_APPS - it could be as simple as having an API promise that the first thing Django does when it "starts" is to run through each application in INSTALLED_APPS looking for and importing an autoload.py module. I imagine we'll find that the time at which models are registered is critical (what if autoload.py wants to use a model that hasn't been loaded in to the AppCache yet?) and may need to do more than one pass through INSTALLED_APPS. Plenty of details to figure out. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Model validation incompatibility with existing Django idioms
A couple of related tickets filed today about model validation: http://code.djangoproject.com/ticket/12513 http://code.djangoproject.com/ticket/12521 The first one describes the issue best - the new model validation code breaks the following common Django convention: form = SecretQuestionForm( {"secret_question":"foo", "answer":"bar"} ) if form.is_valid(): p = form.save(commit=False) p.user = request.user p.primary_contact = somecontact p.save() The problem is that is_valid() notices that some of the required fields in SecretQuestionForm (a ModelForm) have not been provided, even if those fields are excluded from validation using the excludes= or fields= properties. The exception raised is a UnresolvableValidationError. This definitely needs to be fixed as it presumably breaks backwards compatibility with lots of existing code (it breaks a common ModelAdmin subclass convention as well, see #12521). Can we just change the is_valid() logic to ignore model validation errors raised against fields which aren't part of the ModelForm, or is it more complicated than that? Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Design and code review requested for Django string signing / signed cookies
On Jan 4, 6:18 pm, James Bennettwrote: > Simon, the amount of pushback this is getting, and the changes which > need to be made to start bringing it up to snuff, make me feel far too > nervous about this being ready in time to make 1.2 at all. I know > you've put in the effort to shepherd this along, but I'm starting to > think it's time to push this to the 1.3 release cycle (especially > since 1.2 alpha freeze is tomorrow, and I don't think there's any way > it'll be even alpha-ready by then). I certainly don't think we should check this in for the alpha freeze. We do however need to consider the places in Django that are already using hmac / md5 / sha1 (contrib.formtools and middleware.csrf for example). Even if we don't add the signed cookies feature to 1.2, fixing any problems with our existing use of crypto should not be affected by the feature freeze. There's not much point in implementing this logic in several different places, so I think we should keep targeting the django.utils.signed module for 1.2. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Design and code review requested for Django string signing / signed cookies
On Jan 4, 2:45 pm, Jordan Christensenwrote: > Is there a good way to make it forward upgradeable? Allow the > developer to decide on the shorter SHA-1 hash or the (theoretically) > more secure SHA-256? There is - we can expand the BACKEND setting which is already in place for signed cookies (but not for other clients of the Signer class). I think we should do this. For one thing, it would mean we could provide a backend which uses the Google keyczar Python library instead of the code that we write. keyczar is properly audited, but depends on PyCrypto so isn't appropriate as a required dependency of Django. Another thing we can do is use SHA-256 but truncate the HMAC to 128 characters. Apparently it's perfectly fine to do this - it's being discussed in the programming.reddit thread at the moment. -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Design and code review requested for Django string signing / signed cookies
Had some good feedback on news.ycombinator and programming.reddit - you can follow the threads here: http://news.ycombinator.com/item?id=1030290 http://www.reddit.com/r/programming/comments/ald1m/calling_crypto_security_experts_help_review_the/ tptacek on news.ycombinator pointed out a timing attack based on our use of an insecure string comparison (an attack which affected Rails a while ago). We can fix that using a constant time string comparison such as this one: http://code.google.com/p/keyczar/source/diff?spec=svn414=411=414=unidiff=/trunk/python/src/keyczar/keys.py ascii on programming.reddit has convinced me to ditch the sep=":" argument and hard code the separator. Customising that doesn't feel like a feature anyone will ever need. They also repeated the advice to use SHA-256 - I think I'll almost certainly have to give up my quest for shorter signatures :( -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Design and code review requested for Django string signing / signed cookies
>From Jordan Christensen on Twitter: >http://twitter.com/thebigjc/status/7366243197 "@simonw why sha-1 instead of sha-256? NIST has recommended not using SHA-1 in new systems: http://bit.ly/6bIf5h; I chose sha-1 over sha-256 for reasons of signature length. A base64 encoded signature generated with hmac/sha1 is 27 characters long. The same thing using hmac/sha256 is 43 characters long. If you're planning on using signatures in cookies and URLs that's quite a big difference (43 characters is more than half of the maximum 80 characters needed to safely transmit URLs in plain text e-mails, e.g. for account recovery links). My understanding is that the collision weaknesses discovered in SHA-1 are countered by the use of HMAC. Here's Bruce Schneier on the matter: http://www.schneier.com/blog/archives/2005/02/sha1_broken.html "It pretty much puts a bullet into SHA-1 as a hash function for digital signatures (although it doesn't affect applications such as HMAC where collisions aren't important)." Despite the confusing API name, we're doing HMAC here, not digital signatures - so I think we're OK. If I'm wrong I'm sure a crypto geek will set me straight pretty quickly. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Design and code review requested for Django string signing / signed cookies
mp with the signature The second class in the signed.py module is a subclass of Signer that appends a unix timestamp to the string before it is signed. This allows the unsign() method to specify a max_age - if the signed value is older than that max_age, it is discarded. Here's the code: class TimestampSigner(Signer): def timestamp(self): return baseconv.base62.from_int(int(time.time())) def sign(self, value, salt='', sep=':'): value = smart_str('%s%s%s' % (value, sep, self.timestamp())) return '%s%s%s' % ( value, sep, self.signature(value, salt=salt) ) def unsign(self, value, salt='', sep=':', max_age=None): value, timestamp = super(TimestampSigner, self).unsign( value, salt=salt, sep=sep ).rsplit(sep, 1) timestamp = baseconv.base62.to_int(timestamp) if max_age is not None: # Check timestamp is not older than max_age age = time.time() - timestamp if age > max_age: raise SignatureExpired, 'Signature age %s > %s seconds' % ( age, max_age ) return value As you can see, the timestamp is appended to the value before it is calculated, and a max_age can be passed to the unsign() method and will be checked before the string is returned. Again, as a space saving the unix timestamp is a base62 encoded - this shrinks it and makes it suitable for inclusion in a URL (for example). Signing cookies --- Signed cookies are provided using two new methods on core Django objects: a get_signed_cookie() method on the Django request object and a set_signed_cookie() method on the Django response. Here's what a very simple Django view might look like that reads the name from a signed cookie and sets that cookie if a new name has been provided in a POST parameter: def index(request): name = request.get_signed_cookie('name') set_cookie = False if name in request.POST: name = request.POST['name'] set_cookie = True response = render_to_response('index.html', { 'name': name, }) if set_cookie: response.set_signed_cookie('name', name) return response The get_signed_cookie() method is implemented here: http://github.com/simonw/django/blob/signed/django/http/__init__.py#L66 And set_signed_cookie() is here: http://github.com/simonw/django/blob/signed/django/http/__init__.py#L388 Both of these methods take an optional 'salt' argument - but even if you don't provide a salt, the name of the cookie will be used as the salt. If you DO provide a salt the actual salt used will be cookie_name + your_salt. SECRET_KEY rotation --- I'm still working out the details for this, but the final feature we want to provide is a mechanism for rolling out a new SECRET_KEY without breaking everything that has been signed with an old one. I believe this is best practice, but I'm eager to hear if it isn't. The plan is to support an optional OLD_SECRET_KEYS setting which is a list of old secret keys which should still work for unsigning but should not be used for signing. The UpgradingSigner class here is a start at this code: http://github.com/simonw/django/blob/signed/django/utils/signed.py#L142 A piece of Django middleware will be provided that quietly "upgrades" any signed cookies that have been signed using one of the older keys, replacing them with a cookie signed with the current SECRET_KEY. This middleware will need to know the names of the cookies that should be upgraded and what salt was used to generate them. The process for rolling out a new SECRET_KEY then will be this: 1. Put the current secret key in OLD_SECRET_KEYS: OLD_SECRET_KEYS = ['your-current-secret-key'] 2. Put the NEW secret key in SECRET_KEY: SECRET_KEYS = 'your-new-secret-key' 3. Turn on the Django signed cookie upgrading middleware: MIDDLEWARE_CLASSES += ( 'django.middleware.signedcookies.UpgradeOldSignedCookies', ) 4. Tell that middleware which cookies to upgrade: SIGNED_COOKIES_TO_UPGRADE = ( ('name', 'salt-for-name'), ) Now wait a week while a bunch of cookies get upgraded, then remove the key from OLD_SECRET_KEYS. Sending feedback Does this look sane? Have we overlooked anything? Is there anything we can do to make this more secure by default? I'll read any replies here, or you can e-mail feedback to simon AT simonwillison.net. Please say if you don't want stuff sent to that address to be shared in public. Thanks, Simon Willison -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: 1.2 Feature freeze
On Dec 23, 8:34 am, James Bennettwrote: > * URLs-1 (get_absolute_url replacement) The code's not ready - I have the get_url / get_url_path methods but I don't have a good enough hold yet on what actually needs to be done to replace the existing get_absolute_url behaviour and all of it's idiosyncrasies. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Call for feedback: django.utils.signed and signed cookies
Having talked to James about this I'm holding off on the commit until we've had it reviewed by real cryptographers. I'll aim to get it in before the 1.2 beta feature freeze. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Congratulations Alex and Russell on committing multidb!
... and congratulations to Marc Garcia and Jannis Leidel for the i18n/ l10n improvements that just went in as well. Also congratulations to everyone for the other awesome commits going in at the moment. There are far too many congratulations to spell them all out at the moment (with hindsight I wish I hadn't started!). 1.2 is going to rock. -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Congratulations Alex and Russell on committing multidb!
And a big congratulations to all involved. Here's the changeset log (on GitHub since Trac seems not to like being linked to at the moment): http://github.com/django/django/commit/836d297e68d6a63103780295adebf6eaf6779611 And here's the documentation: http://docs.djangoproject.com/en/dev/topics/db/multi-db/ Really excited about this - can't wait to start putting it to good use. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Call for feedback: django.utils.signed and signed cookies
On Dec 22, 6:22 am, Russell Keith-Mageewrote: > As far as the patch itself is concerned, looks good to me. My only > other request would be a serving of dogfood - if we're going to > include a signed cookie module, it would be nice to prove that it can > actually be used by actually using it. I'd love to see the cookie backend of the new django.contrib.messages feature switch over to using get/set_signed_cookie. I'm happy to put together the patch, or alternatively one of the people who worked on that feature can do it. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Call for feedback: django.utils.signed and signed cookies
On Dec 22, 12:52 am, Johannes Dollingerwrote: > I'd like some more kwargs to Signer and TimestampSigner. Mostly what's > inhttp://dpaste.com/136418/(except the `separator` kwarg, which was > a bad idea as it depends on encode()): Signer(serializer=...) and > TimestampSigner(ttl=...). The first few versions of the code had a bunch more stuff along the lines of that dpaste (which expires in 6 days, so here's a gist copy of it: http://gist.github.com/261572 ) After struggling with it for quite a while, I decided that having a single class that handled signing, serialization and compression wasn't the right approach - it was doing far too much. Instead, I changed the design so the Signer's only responsibility was generating signatures, appending them to strings and verifying that they were correct. The encryption/serialization was extracted out and moved directly in to the signed.dumps() and signed.loads() functions. This solved a bunch of problems I was having with the code - too many subclasses, confusing amounts of multiple inheritance for mixing together different subclassed behaviours - and generally made everything feel a lot more cohesive. That's also why I added the BACKEND setting for setting a cookie signing backend - that way, users with specific ideas about how their signed cookies should work can write their own class that does pretty much anything they like. Is there any functionality in particular that you think should be resurrected from the more-complex-signing-classes? I'm very keen on keeping the serialization and compression stuff out of Signer. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: What do people think about the get_absolute_url proposal?
On Dec 8, 3:23 am, Rick Yazwinskiwrote: > I think that this may be too simplified: > protocol = getattr(settings, "PROTOCOL", "http") > domain = Site.objects.get_current().domain > port = getattr(settings, "PORT", "") > > Many sites put load balancers and https hardward acceleration in front > of their web interfaces. This would obscure the protocol and port > info from Django. Aha! I was pretty confused by this thread, since I didn't remember writing the above code. It turns out that's the problem with making proposals like this on a wiki... http://code.djangoproject.com/wiki/ReplacingGetAbsoluteUrl?action=diff=10 My original proposal can still be seen here: http://code.google.com/p/django-urls/source/browse/trunk/django_urls/base.py It's basically this: def get_url(self): if hasattr(self.get_url_path, 'dont_recurse'): raise NotImplemented try: path = self.get_url_path() except NotImplemented: raise prefix = getattr(settings, 'DEFAULT_URL_PREFIX', 'http:// localhost') return prefix + path get_url.dont_recurse = True So for the common case it invents a new DEFAULT_URL_PREFIX setting which can be used to ensure get_url uses the correct domain. If you want to use a threadlocal request for this instead that's fine - just define your own get_url() method that does that. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Call for feedback: django.utils.signed and signed cookies
I've made some changes based on the feedback in this thread: http://github.com/simonw/django/commit/802952bbb8b763e65ee545c6a8f39524b20e147c "Use sha('signer' + secret_key + salt) to derive the key for use in the signature() method, addressing feedback from the django-developers list" The default signature() method now looks like this: def signature(self, value, salt=''): # Derive a new key from the SECRET_KEY, using the optional salt key = sha_constructor('signer' + self.key + salt).hexdigest() return base64_hmac(value, key) The secret key (self.key here) is now never used directly. Instead, a sha1 hash of the salt 'signer' plus the secret key plus any additional salt is used as the key for the signature. sha1 is used here as protection against weird key length extension attacks (like the one that affected the Flickr API recently). http://github.com/simonw/django/commit/4ed44c2bce5000d6c78c3a26b84d08f636b3589c "RAISE_ERROR now capitalised to emphasize that it is a constant" http://github.com/simonw/django/commit/20f3a693b99ec6af0f91eecb31046e8a07dc7151 "Signed cookies now automatically include the name of the cookie as part of the salt" http://github.com/simonw/django/commit/68c52f0b995447d93bce1db486b23a27b918da73 "Moved get_cookie_signer in to utils.signed" New patch is attached to the ticket. Is there anything else I need to address before checking it in? http://code.djangoproject.com/ticket/12417 Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Loading Backends
On Dec 21, 2:22 pm, Marty Alchinwrote: > Looking over Simon's patch for signed cookies, I noticed that yet > another feature needs to write its own "load a backend from a setting" > function. Yup - and as I copied and pasted it from somewhere else I thought exactly the same thing. Is this kind of refactoring something we can do after the 1.2 feature freeze? If so I think it would be worth cleaning up at least some of this stuff. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Call for feedback: django.utils.signed and signed cookies
On Dec 21, 2:40 pm, Russell Keith-Mageewrote: > * I'm not sure I like this being in django.utils. To me, it feels > like something that should be in django.core - along with caching, > serialization, etc, signing is a core piece of functionality that a > website will need to implement. django.utils is full of necessary, but > largely ancillary code. I have to admit I don't 100% understand the difference between core and utils - but I'm happy with moving it across to core if that makes more sense. > * get_cookie_signer() strikes me as something that should be a > general utility in the signing module, not something buried in > django/http. I'd love to see this code factored out as per Marty's suggestion in another thread. I wrote a backend just for signed cookies because that's the one part of the implementation that's "baked in" to core Django APIs - but I expect other bits to be baked in to things like session handling / auth / form wizards etc over time, so being able to over-ride the Signer used for those in the future will be important. > * django.http.raise_error should be RAISE_ERROR, so it's obvious it's > a constant Good point, I'll fix that this evening. > * I'm not sure I follow why we need to use base62 (and therefore > provide our own base encoding method) in the Timestamp signer. OK, you caught me. This is part of my evil scheme to sneak baseconv.py in to Django. I'm using it for the signed cookie timestamp to make it as small as possible (same reason I'm using a base64 of the HMAC hash rather than the regular hexdigest) - since cookies add overhead to every single HTTP request I figure anything we can do to make them smaller is a bonus. I considered using a custom timestamp in seconds since (2009, 12, 1) but that felt a little weird. baseconv.py is actually a lot more important for some of the other ways I use signed cookies. A great example is "recover my account / forgotten password" e-mails. I like sending a signed URL for those (no need to store any state) but it needs to be under 72 characters to fit in an e-mail: http://simonwillison.net/recover/b23/kfQJafvGyiofrdGnuthdxImIJw/ Where b23 is the base62 encoded user ID and the bit after it is a signature. URLs like that often make use of timestamped signatures (I like my recover account URLs to expire after 24 hours) so again it's useful to keep them short. baseconv.py is also useful for things like URL shorteners e.g. http://swtiny.eu/EZj > * In the original mailing list thread, there was discussion about > prefixing the use of SECRET_KEY with some extra data, like the module > name. The 'salt' option is one way to achieve this, but I agree with > Luke and Marty that there should be some mandatory salting. I'll look at that this evening. > * The original mailing list thread (and the wiki) also contained > discussion about how to deprecate/cycle SECRET_KEY values in the case > a value was compromised. Having a working solution for this problem > probably isn't necessary, but it would be good to know that I've got a plan for that as far as signed cookies go - an optional piece of middleware which looks for invalid signed cookies in the request, checks them against an OLD_SECRET_KEYS list and upgrades them if they can be decrypted that way. This can be implemented completely separately from the current code, though the ideal implementation would involve adding a few related methods to the Signer class. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Call for feedback: django.utils.signed and signed cookies
I've uploaded the patch for adding signing and signed cookies to Django: http://code.djangoproject.com/attachment/ticket/12417/ticket12417.diff You can also read the documentation directly on my GitHub branch: http://github.com/simonw/django/blob/signed/docs/topics/signing.txt http://github.com/simonw/django/blob/signed/docs/ref/request-response.txt#L224 http://github.com/simonw/django/blob/signed/docs/ref/request-response.txt#L561 Most of the code lives in django.utils.signed (the low-level signing API) but I've also added a get_signed_cookie() method to HttpRequest and a corresponding set_signed_cookie() method to HttpResponse: http://github.com/simonw/django/blob/signed/django/http/__init__.py#L84 http://github.com/simonw/django/blob/signed/django/http/__init__.py#L406 http://github.com/simonw/django/blob/signed/django/utils/signed.py The code has documentation and unit tests. The documentation isn't 100% complete - I need to improve the explanation of what signing is and why it is useful and document the new COOKIE_SIGNER_BACKEND setting which allows users to swap in their own cookie signing behaviour should they need to. Most importantly though, the implementation has not yet been peer reviewed by real cryptographers. With that in mind, would it be appropriate to check this in before the 1.2 freeze? We would certainly get the code reviewed before the final 1.2 release. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: adding rosetta for enhanced user experience
On Dec 14, 9:41 pm, Suno Anowrote: > What do folks think about shippinghttp://code.google.com/p/django-rosetta > with Django? Enabling it per default even? imho that app is totally > worth being shipped with Django per default. This came up a couple of months ago. Here's why I don't think it's appropriate to ship with Django: http://groups.google.com/group/django-developers/msg/bfd9c35fb95bb35a Basically, it turns out most translators already have a preferred toolchain and may well not want to use a web-based tool. -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
What do people think about the get_absolute_url proposal?
This made it to the 1.2 feature list: http://code.djangoproject.com/wiki/ReplacingGetAbsoluteUrl If we want this in 1.2, it could be as simple as merging the get_url / get_url_path methods in to the base Model class, rolling a few unit tests and writing some documentation. It feels like we should discuss it a bit first though - the proposal hasn't really seen much discussion since it was originally put together back in September last year. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Multiple database support: Request for feedback and testing
On Dec 5, 4:20 pm, Russell Keith-Mageewrote: > Trust me - I don't want to do mindless busy work. However, we need to > have some sort of answer for the admin interface - Django's admin is a > big selling point for Django for some people, so we can't really > introduce a huge new feature, and then say "but you can't use it in > admin". I'm interested in making the least intrusive change that is > possible without hamstringing future multi-db interfaces. It strikes me that the admin issue should be solvable entirely in django.contrib.admin without any changes to the multidb code itself. Right now you can get most of the job done using a ModelAdmin subclass: from django.contrib import admin from blog.models import Entry class EntryAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): obj.save(using='otherdb') def queryset(self, request): return Entry.objects.using('otherdb').all() admin.site.register(Entry, EntryAdmin) I haven't tested the above so it's probably missing a few cases (save_fieldsets for example perhaps) but if we document it I think it's a good enough solution for the moment. Even if we need to refactor ModelAdmin a bit to ensure the right hooks are available it still shouldn't be a massive change. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Multiple database support: Request for feedback and testing
On Dec 4, 8:38 am, Simon Willison <si...@simonwillison.net> wrote: > We now have two blog posts in each database. But, if I do the > following: > > e1.save(using = 'db2') > > It has the effect of replacing e3 with the values from e2, since the > primary keys collide with each other. I meant to say - the fix is clearly to call save() with the force_insert=True argument, but it's easy to miss that. Worth explicitly highlighting in the multi-db docs I think. -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
Re: Multiple database support: Request for feedback and testing
On Dec 3, 4:10 pm, Russell Keith-Mageewrote: > Alex Gaynor's GSoC project to add multiple database support to Django > is on the final straight. The only piece of the puzzle that is left is > updating contrib.gis - but this hopefully won't require any major > changes outside of the gis tree itself. > > Therefore, I'd like to call for feedback and testing of the branch. I tried this out yesterday - it's excellent. The combination of the new DATABASES setting and QuerySet.using() turns out to be exactly enough to get all sorts of interesting work done. It neatly fulfils the three requirements set out in the original ticket (replication / sharding / hosting different applications on different databases). A couple of observations. Firstly, there's a gotcha involving saving existing objects to a new database: e1 = Entry.objects.using('db1').create(title = "A blog post", body="...") e2 = Entry.objects.using('db1').create(title = "Another blog post", body="...") e3 = Entry.objects.using('db2').create(title = "Another blog post", body="...") e4 = Entry.objects.using('db2').create(title = "Another blog post", body="...") We now have two blog posts in each database. But, if I do the following: e1.save(using = 'db2') It has the effect of replacing e3 with the values from e2, since the primary keys collide with each other. This behaviour makes sense if you think about it for more than a moment, but still probably counts as a gotcha. Worth mentioning in the documentation at least. I could see this pattern biting people since that's the obvious way to copy an object from one database to another. Secondly, a question: Is there an idea for how this might be made to work with the admin interface? I was asked this question at DJUGL last night and wasn't sure of the answer. Fantastic work on this, very excited to see it merged to trunk. Cheers, Simon -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
How hard would it be to make bits of Django compatible with async servers?
I've been getting very excited about Node.js recently: http://simonwillison.net/2009/Nov/23/node/ It's basically Twisted / Tornado but in JavaScript, and with the huge advantage that, because it's brand new, it doesn't have any legacy blocking APIs. Database access looks like this: c.query("select * from articles").addCallback(function(rows) { pretty_print(rows); }); Even filesystem access is non-blocking: posix.cat("/etc/passwd").addCallback(function(content) { puts(content); }); This made me think about non-blocking IO and Django. Theoretically, many of the services that Django provides could be used in a non- blocking environment such as that provided by Twisted or Tornado: * URL routing shouldn't need to be blocking - it's just dispatching to a function based on a regex (though this is stymied by thread locals) * Form handling shouldn't need to block on I/O * If we cache templates in memory instead of reading from disk each time, rendering them shouldn't need to block on IO either * SQL statement generation with the ORM shouldn't need to block either That last one is particularly interesting to me. My understanding is that much of the ORM refactoring for multi-db consisted of improving the separation of SQL generation from actual database interaction. Being able to do something like this would still be incredibly useful: def my_async_view(request, response): query = Blog.objects.filter(pubdate__year = 2009).exclude (tag__slug = 'sport') def done(rows): response.render('blog.html', {'rows': rows}) db.execute_async(query, done) The db.execute_async method would take a queryset and a callback, execute the query asynchronously and pass the result to that callback. I've invented an imaginary potential async replacement for the blocking response=view(request) idiom. I don't think async support should be baked in to Django core, but it's a very interesting thing to think about. Should we eventually break Django up in to smaller reusable libraries this kind of thing would be an exciting use case. -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=.
Should docs.djangoproject.com link to 1.1 frozen docs by default, not SVN dev docs?
Now that 1.2 features have started to merge (great work everyone involved with the Email backends and ManyToMany refactorings, they look fantastic) we're entering one of those relatively rare periods of instability in trunk. This is exactly the kind of time that we want most of our regular users to be sticking with the 1.1.1 release, while the super-engaged community members try out the new stuff as it's added. There's just one problem: http://docs.djangoproject.com/ defaults to displaying the development docs. In fact, there isn't even an option to see frozen docs for 1.1 (just an option to see them for 1.0). These are going to start being pretty confusing for 1.1.1 users, for example the e-mail docs now cover backends: http://docs.djangoproject.com/en/dev/topics/email/ We include "New in Django Development version" warnings, but it still feels a bit odd. In a post-1.0 world, I think it would make more sense for the documentation linked to directly from the docs.djangoproject.com homepage to cover the most recent official release, with a bit less emphasis on the development version's docs. Basically what the Python docs at http://docs.python.org/ do. I may have missed a previous conversation about this, if so please feel free to direct me to the old thread. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Best place for code that processes stuff from settings.py once (for logging implementation)
On Oct 11, 2:32 am, Simon Willison <si...@simonwillison.net> wrote: > Is there a straight forward solution to this that I've been missing, > or is it an ongoing problem? If it's a problem, can we fix it? What > makes it so difficult to fix (I'm going to guess there's no easy > solution, or we would have sorted it out ages ago)? Are there any > previous discussions I should be reading to catch up on this? On Twitter Malcolm pointed me here: http://code.djangoproject.com/ticket/5685 --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
I'm now tracking the logging implementation in ticket #12012: http://code.djangoproject.com/ticket/12012 I've started posting patches from my branch there. Again, this is just exploratory code at the moment but I'm keen to receive as much feedback on the implementation as possible. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Best place for code that processes stuff from settings.py once (for logging implementation)
I've got to the point in the logging implementation where I want to add support for logging related settings in settings.py. The current idea (suggested by Ivan Sagalaev) is to allow for a standard Django-style setting that look something like this: LOGGING = { 'django.db.sql': { 'handler': 'django.utils.log.StdErrHandler', 'level': 'DEBUG', }, 'django.errors': { 'handler': 'logging.handlers.SMTPHandler', ... } } So each key is the name of a logger, and the value is a dictionary that configures various aspects about how log events sent to that logger be processed (what levels to pay attention to, what handler to use etc). If a handler isn't mentioned in the LOGGING dictionary (it will be empty by default) then all log messages sent to that handler will be silently discarded. To implement this, I need to write some code that executes only once, iterates over the django.conf.settings.LOGGING dictionary and uses it to make the relevant calls to the Python logging framework to set everything up - the above should map to code something like this executing: logger = logging.getLogger('django.db.sql') logger.setLevel(logging.DEBUG) logger.addHandler(django.utils.log.StdErrHandler()) logger = logging.getLogger('django.errors') logger.addHandler(logging.handlers.SMTPHandler(...)) Here's the problem: I need the above to happen once, on startup, some time AFTER the user's settings have been loaded. I can't figure out where the appropriate place to do this is. The best example I've found of code that executes once in Django core is the code in the Settings class constructor: http://code.djangoproject.com/browser/django/trunk/django/conf/__init__.py#L62 This is where the time.tzset() call based on the TIME_ZONE setting happens, for example. Unfortunately, that code executes the first time anything attempts to access a property on the django.conf.settings module (which is a LazySettings module until the first time it is accessed). I could put the logging stuff in there, but it feels like a bit of a cludge. The other interesting happens-once execution point I found is the AppCache class here, which is instantiated once the first time the django.db.models.loading class is imported: http://code.djangoproject.com/browser/django/trunk/django/db/models/loading.py#L15 It appears to use the terrifying Borg pattern to avoid being instantiated more than once. Neither of these seem like particularly suitable places to put code that configures logger objects based on the LOGGING setting. This relates to a wider problem I've had when working with Django (which I've seen crop up all over the place, but I'm not sure there's a best practice for handling) - what to do with Django application/ project code that should only be executed once. We had this problem with class registration for the admin, and ended up hacking around it with a call to admin.autoload() in the urls.py file - which seems to have resulted in urls.py becoming a defacto standard place for putting code that's meant to run once on startup. For logging, I want advanced users to be able to write their own Python logging configuration code (see example above) rather than using the LOGGING setting. Should I tell them to put that in urls.py as well? I'm ashamed to admit it, but I tend to shy away from using signals in my own code purely because I don't know where I should put the code that registers them. Is there a straight forward solution to this that I've been missing, or is it an ongoing problem? If it's a problem, can we fix it? What makes it so difficult to fix (I'm going to guess there's no easy solution, or we would have sorted it out ages ago)? Are there any previous discussions I should be reading to catch up on this? Alternatively, should I just stick my log configuring code in the Setting class constructor and leave well alone? Thanks, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Tutorial Refresh
On Oct 10, 2:04 pm, Ned Batchelderwrote: > My strong feeling is that these two goals will quickly become impossible > to reconcile. I think the idea of a conference site is a good one > (everyone will understand the problem domain, lots of interesting > avenues to explore, it's not yet-another-blog), but aiming for it to be > the actual site used for DjangoCon will not work in the long run. I absolutely agree that aiming for the site produced at the end of the tutorial to be the exact site used for DjangoCon will lead to both goals being fulfilled poorly, but I still think they can be addressed at the same time. Build out a basic conference site for the tutorial, then use that as the basis for the full DjangoCon site (which can fork off from the tutorial to add more features). I'd love to see the final DjangoCon site being open source and demonstrating Django best practices. That said, until we hear from the DjangoCon organisers we won't know if this is a good idea from their point of view. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
On Oct 10, 1:41 pm, Simon Willison <si...@simonwillison.net> wrote: > Oops, yes you're right - I misread the numbers. A 2.5 second different > would correspond to around 350,000 log messages (assuming the rate of > 130,000/second from my microbenchmark) - I have no idea how many > statements the unit tests execute in total. Once I've written a bit > more code of course I could always find out using a logger... I just hacked in a logger that increments a counter for every message - it indicates that there are 158,527 SQL statements executed by the test suite, which means we should expect to add slightly over a second to the time taken for the overall unit tests based on the microbenchmark. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
On Oct 10, 12:55 pm, Luke Plantwrote: > > master: 314.442s > > logging: 317.096s > > > Since there's nothing at all in my logging code that will speed > > anything up, I'm putting that down to chance (I did run the suite a > > few times first to "warm up" the VM I used, but like I said, this > > is pretty much the opposite of science). > > Those numbers are the time in seconds, right? In which case your > branch is slower, not faster, as I think you are implying. It could > still be down to chance, but its only 1% which would be an acceptable > hit for me anyway. Oops, yes you're right - I misread the numbers. A 2.5 second different would correspond to around 350,000 log messages (assuming the rate of 130,000/second from my microbenchmark) - I have no idea how many statements the unit tests execute in total. Once I've written a bit more code of course I could always find out using a logger... Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
On Oct 9, 4:54 pm, Jacob Kaplan-Mosswrote: > One big question I have is about performance: have you done any a/b > testing against trunk to see how much adding logging -- especially > upon every SQL query -- impacts performance? > > For me, at least, performance is going to be the critical factor. It's > clear that even a do-nothing logger will add some overhead. If we're > talking fractions of percents here, fine... but if there's a > measurable performance hit that's going to be a big problem, and it's > probably best to be tracking speed as we go along here. Nothing scientific yet - I've run the full unit test and got these results: master: 314.442s logging: 317.096s Since there's nothing at all in my logging code that will speed anything up, I'm putting that down to chance (I did run the suite a few times first to "warm up" the VM I used, but like I said, this is pretty much the opposite of science). Microbenchmarks I performed with the timeit module suggest we can log to a NullHandler logger at a rate of over 100,000 log messages a second, which is why I haven't paid performance much attention since running the microbenchmark. Here's how to replicate it (using Python 2.6, which lets you pass a callable to the timeit.timeit function): import logging class NullHandler(logging.Handler): def emit(self, record): pass logger = logging.getLogger('django') logger.addHandler(NullHandler()) logger.propagate = False time_for_a_million_messages = timeit.timeit(lambda: logger.info('a log message'), number=100) messages_per_second = 1 / (time_for_a_million_messages / 100) I ran that just now and got 137,223 messages per second. I figure even a really heavy Django page will execute maybe a couple of hundred SQL queries, which would add about 0.0015 of logging time if no handler was hooked up. Hence why I'm not too worried. Is there a reasonable benchmark I can be using for this? The test suite run time doesn't seem particularly finely grained. I know Jeremy Dunck was talking about this a while back. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Tutorial Refresh
Put me down as a other +1 for a full site tutorial, especially one that covers pip, virtualenv, unit testing and the like. I have a suggestion for a site, too: How about the conference website for the next DjangoCon? It's meant to be a community run conference so the job needs to be done at some point, and building it as a community tutorial project feels like it would be a nice fit. A conference site is neat because it's a good example of a content oriented site that isn't a blog, but can still take advantage of generic views (and the admin, of course). It can be as simple or as complicated as needed for the tutorial. We can even include API driven features (recent tweets / photos from Flickr etc) which would be a good way of demonstrating advanced concepts like caching. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
On Oct 9, 11:12 am, Luke Plantwrote: > >http://github.com/simonw/django/tree/logging > > Is there some easy way to see the patch? Preferably a link which will > just show the diff between the latest of your branch and trunk, but > failing that, a recipe of commands using git (for those of us who > haven't bothered to learn git properly yet). Once things are a bit further along I'll start posting patches to the ticket tracker, but for the moment you can see the changelog here: http://github.com/simonw/django/commits/logging There are only two relevant commits: http://github.com/simonw/django/commit/b5227e1ac1d70b1f936ee69d6e347d8148df461e http://github.com/simonw/django/commit/65ff505718538124ee2979fb60dfe1a37ca1b8bc But since that means you have to patch together what's going on from the two commits, I've pasted a full diff to trunk here: http://dpaste.com/hold/104862/ --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
For anyone interested in following this, I've just started a (currently experimental) branch on GitHub: http://github.com/simonw/django/tree/logging So far I've added a 'django' logger which is silent by default, and hooked up a new CursorLoggingWrapper to log all SQL statements from the ORM to it. I've also modified the runserver command so you can use the following to watch the execute SQL flow past on the console: ./manage.py runserver --loglevel=django.db.sql:info None of the implementation code is intended to be production quality yet (I'm just experimenting for the moment), but I'm very interested in feedback on the approach. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Brand new projects should pass their tests (the django.contrib.auth thing from #7611)
On Oct 6, 1:25 pm, Russell Keith-Mageewrote: > I think we need something else. In particular, I think we need to > address the problem at a slightly deeper level - we need to > acknowledge that we don't differentiate between application tests and > integration tests within Django's test framework. That's a really interesting idea - I've been thinking about it over the past couple of days and it does seem to make sense. I'm having trouble imagining exactly how it would work, but I can see that tests which identify problems with the user's configuration are useful, but should absolutely be kept separate from those tests that verify that the application works as a standalone chunk of code. Are we talking about something like this? ./manage.py test # run application tests ./manage.py test --integration # run integration tests > 1. Reverse the decision of #7611, and make the current contrib.auth > test suite a genuine collection of app tests. > > 2. Add extra tests to validate the integration case. These tests > would be conditional, depending on exactly what has been deployed. For > example: one test would look to see if > contrib.auth.views.password_change has been deployed in the project. > If it has, then the test would try to GET the page. The test passes if > the page renders without throwing a missing template warning. However, > if the view isn't deployed, the test is either not run, or is passed > as a no-op. Essentially, the integration tests should be trying to > catch every way that you could misconfigure your deployment of an > application in a project. Conditional tests sound a little bit brittle to me - I think I prefer the model where a user explicitly requests the integration tests to be run. > Making this happen will require two pieces of infrastructure: > > * Firstly, we need a way to make app tests completely independent of > the project environment. We started down this path when we added > TestCase.urls, and the patch on #7611 adds another little piece of the > puzzle. What we really need is a way to address this consistently for > _all_ application settings - including those provided by the > application itself. However, it isn't as simple as creating a new > settings object, because some settings - such as database settings - > need to be inherited from the test environment. This is really interesting, because it fits in with my personal vendetta against settings.py as a whole - the single reason I dislike settings.py is that I often find myself wanting to use different settings for different parts of the same application. Running tests feels like an extension of that desire (and is in many ways a more obvious use case). > * Secondly, we need to make sure that we can easily establish if > integration conditions need to be tested. reverse() already does much > of the job here, but some helpers to make it easy wouldn't go astray. As someone who likes to experiment with alternative ways of constructing an application (see djng) I'm still not a big fan of reverse, which tightly couples me to defining all of my URLs in urls.py with references to real solid functions (rather than re- dispatching through whatever crazy mechanism takes my fancy on that particular day). Again, it might turn out that there's a nicer alternative to integration tests that attempt to run conditionally on configuration. I'm very unclear on how any of this would work though. It sounds to me like splitting tests in to application v.s. integration tests is going to be a lot of work - work that's worth doing, but it's not going to be a quick fix. I'd like to find a quick temporary fix for the auth-tests-fail-by-default problem that can at least resolve this particular issue rather than holding out for a large scale refactoring of the test framework. Shipping default registration tests with the contrib.auth app feels like the easiest option here, especially since default templates would be a useful feature of that part of the framework anyway. If we were to ship default templates, simply using {% extends base %} and providing an argument to the generic views that allows the user to specify their own base template would be enough to ensure easy integration with a custom design (and hence work around what I assume is the reason we didn't ship default templates in the first place). Does that sound reasonable? Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Brand new projects should pass their tests (the django.contrib.auth thing from #7611)
One of the things that has been established at DjangoCon is that, as a community, we don't have a strong enough culture of testing. This is despite Django shipping with some good testing tools (TestClient and the like). Anything we can do to make testing more attractive is a Good Thing. In my opinion, one of the biggest psychological barriers to testing is this: $ cd /tmp $ django-admin.py startproject foo $ cd foo $ echo "DATABASE_ENGINE='sqlite3';DATABASE_NAME='data.db'" >> settings.py $ python manage.py test Creating test database... Creating table auth_permission ... EE..E...EEE.. == ERROR: test_password_change_fails_with_invalid_old_password (django.contrib.auth.tests.views.ChangePasswordTest) ... TemplateDoesNotExist: registration/password_change_form.html On a brand new project, the tests fail. This has been discussed before: http://groups.google.com/group/django-developers/browse_thread/thread/ac888ea8567ba466 http://code.djangoproject.com/ticket/7611 The decision was to wontfix it, since the test failures are correct - if you don't have those templates set up, the auth application won't work. That certainly makes sense, but the larger issue remains: a brand new project doesn't pass its tests out of the box. A number of potential solutions come to mind: 1. Remove django.contrib.auth from the default set of INSTALLED_APPS 2. Add django.contrib.admin to the default set of INSTALLED_APPS so that the templates are available 3. Ship the registration/ family of templates in the contrib.auth app 4. Modify the contrib.auth tests to first alter TEMPLATE_DIRS to ensure the templates are available 5. Remove the views from contrib.auth and move them to contrib.authviews - which isn't installed by default 6. Something else entirely I quite like option 1 - I don't think including contrib.auth in brand new projects is particularly useful. We can change the documentation to note that if you want to add contrib.admin you'll need to inclued contrib.auth as well. I don't like option 2. Option 3 is a fair bit more complicated than it sounds - we would need to ensure that those templates can still be used by the admin but with the admin's outer design applied (probably by using {% extends base %} and having base be a variable that is independently twiddled with somehow). Option 4 would break the idea that the auth tests should tell you if the templates are misconfigured. Option 5 would add yet another dependency to the admin. Option 6 would be welcome if anyone has any ideas. I think this issue is well worth solving. If we DO solve it, we could even think about adding some stuff about running "./manage.py test" to the tutorial. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Oct 5, 6:33 pm, Matt Brubeck <mbrub...@limpet.net> wrote: > On Sep 24, 10:18 am, Simon Willison <si...@simonwillison.net> wrote: > > This offers two APIs: sign/unsign and dumps/loads. sign and unsign > > generate and append signatures to bytestrings and confirm that they > > have not been tampered with. dumps and loads can be used to create > > signed pickles of arbitrary Python objects. > > Unpickling data sent by the client seems dangerous, since it can > execute arbitrary code on the server [1]. Obviously signing the data > goes a long way toward preventing such attacks, but I'm still not > comfortable with the idea that a leaked signing key could instantly be > escalated to arbitrary code execution. (For example, if the config > files are exposed through a misconfigured web server or accidentally > checked into public source control.) If you use JSON or some other > object serialization by default, then the damage from a leaked secret > key would be much more limited in most cases. You know what, I have to admit I hadn't really thought about JSON as an alternative. Obviously I knew that unpickling was unsafe - that's one of the reasons I'm so keen on signing - but it really doesn't make sense to expose this kind of risk if it's not necessary. The pickling trick is cute, but is the convenience of being able to pass any pickle- able object around really worth the risk? I don't think it is - I think I'll ditch the dumps/loads signed pickle methods in favour for similar functionality that uses JSON instead. Other than dates being a bit more annoying to pass around, I really don't think that telling people they can only dumps/loads JSON-encodable data would be a huge burden. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Branchy Django developement on GitHub
Thanks for putting this together - that's a really useful summary of commands. Any chance you could save it on the wiki somewhere? Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding an option to re-test only failed tests
On Oct 2, 12:09 pm, Ned Batchelderwrote: > I would think the same logic applies to Django. Nose needs to work with > lots of different projects, so they can't own the Django details, since > by that logic they'd also own the TurboGears logic, the Pylons logic, > the Twisted logic, etc... But the Nose plugin API isn't changing much > now, so Django could include a nose plugin which would only have to > change when Django details change. And we'd get all sorts of nose > features without having to implement them in the Django code. That seems to make sense. I rather like the gesture here as well - shipping plugins that get Django to work well with other parts of the Python ecosystem sends a powerful message that Django wants to work well with other parts of the Python ecosystem. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding an option to re-test only failed tests
On Sep 30, 5:47 am, Russell Keith-Mageewrote: > I'm yet to be convinced that Nose should be the default test runner > for the simple reason that it doesn't come out of the box with Python. > However, I agree that using Nose with Django should be as painless as > possible. I included the TEST_RUNNER setting specifically for this > reason. Agreed - adding nose as a dependency for running unit tests would make people less, not more likely to run them. > Then there is the issue of whether Django should be responsible for > shipping a Nose-compatible test runner, or whether that is Nose's > responsibility. Historically, I've been of the opinion that it should > be Nose's responsibility to ship a test runner, but I'm open to other > opinions on this. >From the point of view of encouraging the usage of nose, either would work fine. I think this is fits in to the conversation at DjangoCon about how we should go about encouraging Django users to explore the wider Python ecosystem. The important thing is that we can have some official (or semi-official) documentation somewhere saying "to access enhanced test running commands, install nose and drop this string in to your TEST_RUNNER setting." The string itself could point at dango.something or nose.something, the important thing from my point of view is that they don't have to grab a test runner script from another third party, then figure out where to put it within their project. If nose don't want to ship the test runner, I'd be fine with putting it in django.contrib somewhere. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
So I've read through the Python Logging 101 (really useful) and the logging docs: http://plumberjack.blogspot.com/2009/09/python-logging-101.html http://docs.python.org/library/logging.html Here's my understanding of what we need to do for Django. 1. Create a 'django' logger somewhere in the framework that will always be executed if part of Django has been imported - would the django/__init__.py file work? Configure that with a NullHandler, and set it NOT to propagate events to the root logger. That way we can start using 'django.*' loggers throughout the framework but none of the messages will be sent anywhere without further configuration. The code should look something like this: import logging class NullHandler(logging.Handler): def emit(self, record): pass logger = logging.getLogger('django') logger.addHandler(NullHandler()) logger.propagate = False NullHandler is a generally useful class (I'm surprised it's not part of the core logging library), so we should probably put that in django.utils.log. The NullHandler is there purely to prevent the one- off "you haven't configured a handler yet" error that gets sent to sys.stderr. 2. Start using loggers within the Django framework itself. The most obvious place to start is SQL queries - at the point where we execute SQL, we should do this: logging.getLogger('django.db.sql').debug(sql_to_execute) That logs the SQL to a 'django.db.sql' logger - which is a child of the 'django' logger and hence will be swallowed by the NullHandler. Another place we could use logging is to record cache gets and misses: logging.getLogger('django.core.cache').debug('Cache miss for key %s', key) And for sending e-mail: logging.getLogger('django.core.mail').info('Mail sent to %s', to_email) The logger names reflect the structure of Django up to a point (django.db) but I don't think there's anything wrong with straying from that convention (django.db.sql for example) provided the prefixes are sensible. 3. Add a bunch of syntactic sugar for making log messages visible at various points within Django. For example: ./manage.py runserver --log-level=django:info Would cause the runserver to first configure the 'django' logger to print all messages of level 'info' and higher to stdout. ./manage.py runserver --log-level=django:info --log- level=django.db:debug Same as above, but also configures django.db messages of debug or higher to display (I'm sure the command line syntax could be improved). By default, runserver would display no log messages at all. The same arguments could also work for ./manage.py test: ./manage.py test --log-level=django.db.sql:debug Hmm... maybe the --log-level argument could work for ALL management commands. My philosophy here is that log messages should be ignored unless explicitly told otherwise. Django gets run in various different ways - runserver, test and in deployment under mod_wsgi/FastCGI/etc - and it's not at all obvious what the default log output behaviour should be. As long as we make it extremely easy to see log messages if we want them I think having them off by default makes sense. It also ensures no surprises for people upgrading from 1.1 to 1.2. 4. Add a way to configure loggers in Django's settings.py file, in particular for use in production. I'm not sure if these settings should be ignored when running under other circumstances (./manage.py test etc) in favour of the command line option, or if they should still take effect. I quite liked Ivan's suggestion: LOGGING = { 'django.db.sql': { 'handler': 'django.logging.FileLogger', # WatchedFileLogger copy 'filename': '/tmp/django-sql.log', 'level': 'debug', }, 'django.core.cache': { 'handler': 'logging.handlers.HTTPHandler', 'host': '...', 'url': '', 'format': '' }, 'django.errors': { 'handler': 'logging.handlers.SMTPHandler', ... } } django.errors is where we get to replace the current "e-mail 500 errors to an ADMIN" functionality. There should also be an option for advanced users to ignore the declarative syntax entirely and just provide a bunch of code that configures logging in the traditional way: import logging django_logger = logging.getLogger('django') django_logger.setLevel(...) django_logger.addHandler(...) # etc I'm not sure where that custom code should live - right there in settings.py? At any rate, I think it's vital that people can use the low level logging configuration API if they want to. I'd rather not encourage people to use the logging module's support for .ini style configuration, just because Django already has its own configuration standards. That's not to say people can't call that from their own code if they want to, but I don't think we should emphasise that ability. 5. Document how users should go about implementing their own loggers. I think we should tell people NOT to put them within the 'django' logger
Re: Adding an option to re-test only failed tests
On Sep 29, 7:34 pm, Rob Madolewrote: > TEST_RUNNER = 'django.contrib.test.nose.run_tests' > > There might be some futzy bits to make that actually work, but I think > it'd doable. I'd love to see this working. Obviously this would work just as well implemented as an external project - but if it's as useful as it sounds I'd personally be up for including it in core, if only to promote the usage of nose amongst Django developers (and hence help weaken the impression that Django doesn't integrate well enough with the wider Python community). Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding an option to re-test only failed tests
On Sep 29, 5:03 pm, Rob Madolewrote: > I've been using nose for our tests, and one of the features that I > really like is the ability to run the tests again but filter only the > ones that caused a problem. > > I'm thinking it would look something like this > > ./manage.py test --failed > > Does this sound worthwhile to anybody? I don't understand how this works - does it persist some indication of which tests failed somewhere? If so, where? If we're talking about features from nose, the two I'd really like in Django's test runner are --pdb and --pdb-failures: --pdb = when an error occurs, drop straight in to the interactive debugger --pdb-failures = when a test assertion fails, drop in to the debugger Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Model.objects.raw() (#11863)
On Sep 29, 2:24 am, SeanOCwrote: > During the Djangocon sprints I started to work on a patch which would > add a nicer interface for dealing with raw SQL queries. While there I > talked to RKM about where it should fit into the ORM API and where in > the code base should live. I've finally gotten around to finishing > the code I wrote during the sprint and have posted a patch to the > related ticket (http://code.djangoproject.com/ticket/11863). You can > also get the code fromhttp://github.com/SeanOC/django. I've had a bit of a think about this, and there are a couple of things I'd be very keen on seeing supported by this feature. I have a nasty feeling they won't be that straight forward though. The first is that I'd like it to be compatible with deferred loading of model attributes - I haven't looked in to it, but my hunch is that this won't be too hard (it might even work in its present form without any further changes). The second one is probably a lot harder - it feels to me like this feature would be much more useful if it could perform select_related style graph population. One of the key use-cases for raw SQL is improving performance - writing queries which perform better than the ORM (SQL optimisations, or queries that hit an alternative view or use a stored procedure or similar). It's very plausible that a developer might want to write a custom query that populates a full graph of objects, just like select_related() does. It would be really useful if the QuerySet.raw() method let them do that. I haven't looked at how much work it would be to support graph population - it will certainly complicate the user-facing API, and it might require a bunch of work at the ORM level. If it's just too much hassle I think the feature would be worth including without it, but it's certainly worth some further investigation. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
On Sep 29, 9:36 am, Vinay Sajipwrote: > Simon, I'm the author of Python's logging package. Sorry for the delay > in replying, I've been away from this list awhile. I think the "Java > heritage shines through" is just FUD. Hi Vinjay, Thanks for dropping by. Firstly, I'm sorry for disparaging of your work. I mis-spoke when I said the logging module wasn't "nicely designed" - I obviously don't believe that, since I'm very keen on including it in Django. I should have picked my words much more carefully. The point I intended to make is that using the logging module correctly requires quite a lot of knowledge on the part of the developer - there's a lot to understand in there. When I talk about a "thin wrapper" for Django really I'm really just talking about smart defaults - ensuring that Django users can start using logging without needing to know anything more than "import this and call the log.error () method", but that the full power of the logging library is still available once they need it. So again, I apologise for my extremely poor choice of words - that was decidedly unclassy. I'm excited that you're interested in helping us integrate logging with Django in the best possible way. Thanks, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Model.objects.raw() (#11863)
On Sep 29, 2:24 am, SeanOCwrote: > During the Djangocon sprints I started to work on a patch which would > add a nicer interface for dealing with raw SQL queries. While there I > talked to RKM about where it should fit into the ORM API and where in > the code base should live. I've finally gotten around to finishing > the code I wrote during the sprint and have posted a patch to the > related ticket (http://code.djangoproject.com/ticket/11863). You can > also get the code fromhttp://github.com/SeanOC/django. I'm a big fan of adding this feature - I firmly believe we should be encouraging people to roll their own SQL where necessary (it's the ultimate answer to complaints about missing features in the ORM), and I don't think just telling them to instantiate their own cursor is a good enough answer. It's worth talking to Jacob about this - last year he had something like this in a private branch, but I don't think he ever released it. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Better HTML4 support
On Sep 28, 6:57 pm, Rob Hudsonwrote: > For lack of knowing about anything better, I keep falling back to > Werkzeug's HTMLBuilder class[1]. Pulled out and stripped of comments, > it weighs in at 77 lines of code... That's not so bad. I was worried about pulling in a large dependency, but 77 lines (probably dropped in to django.utils.builder or similar) isn't particularly alarming. I'm still a bit sceptical of introducing another markup abstraction just to solve this one problem. I wonder if it could be used to tackle the RSS/Atom generation problem as well? > I agree with what I think I'm reading here -- a goal being to give > designers more fine grained control over the form and form elements at > the template level. Yes, that's exactly it. Designers should be able to do anything they like with forms at the template level (hence the {% field form.name class="foo" %} suggestion). Again, this makes me slightly cautious about the HTMLBuilder approach since exposing that at the template level is virtually impossible. > I think you might want both 1 and 3. (1) for those that want finer > control or just don't want to use the underlying HTML wrapper, and (3) > for those that do. > > Would it be something to consider adding special case tag, like > comments, to represent the self closing slash depending on current > context's doctype? For example, something like {% / %}? I'm really not in favour of 3. 1 I think is OK - as I mentioned above, I added it to django-html as {% slash %} and it's actually not that unpleasant. I think I'd rather avoid adding custom syntax like {% / %} just to support this one tiny edge case (I strongly expect most Django developers won't ever want to write code that's doctype agnostic - and as Max mentioned, HTML5 grandfathers in the /> syntax - the tag will be used strictly by perfectionists). Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Better HTML4 support
On Sep 26, 7:33 pm, Simon Willison <si...@simonwillison.net> wrote: > 1. a {% selfclose %} template tag: > > <br{% selfclose %}> > > {% selfclose %} outputs either blank or " /" depending on the doctype. I've added an experimental {% slash %} tag to django-html to address the reusable XHTML/HTML templates problem. It's actually not as horrible as I first thought - you end up writing template code like this: <br{% slash %}> It's not exactly beautiful, but it's the simplest thing that could possibly work. Most Django developers who aren't writing code designed to be used with differing doctypes won't ever have to use it. In the absence of a better idea I'm pretty happy with it. http://github.com/simonw/django-html Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Better HTML4 support
On Sep 28, 5:20 pm, Max Battcherwrote: > I really don't see what the fuss here is about. If we are worried about > forwards-compatibility, HTML 5 takes care of it. If we are worried about > better backwards-compatibility with HTML 4, everyone else is saying that > the future is now and the focus should be HTML 5... > > What is this argument really about? http://www.djangoproject.com/ calls Django the web framework for "perfectionists with deadlines". This is a perfectionist issue. If the problem was incredibly hard to solve or involved breaking backwards compatibility I'd drop this, but I don't think it's a particularly big or difficult change. The django-html approach even gives us a useful extra feature - it allows template developers to add new attributes to form widgets without needing changes made to the underlying Python form definitions: {% field form.name class="foo" onfocus="bar()" %} It's not just me that gets annoyed by this - when I'm teaching Django to client-side engineers this tends to come up a lot - and I find the answer a bit embarrassing. It's basically the only place in Django that the template author can't control the markup, and good client- side engineers are pretty picky. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Better HTML4 support
On Sep 27, 10:49 am, veenawrote: > my bits to discussion about supporting various (X)HTML versions. > > 1) Problem with (X)HTML in python code (in applications) > I discovered this python packagehttp://pypi.python.org/pypi/html/1.6 > It allows you to write "python like HTML syntax" and generates HTML or > XHTML. Something like that might be an option for cleaning up the way markup is generated within the forms framework itself, but ultimately I think adding an entirely new Python-based generation method just to output a few strings wouldn't be worth the added dependency. > 2) Problem with (X)HTML in templates > I think there should be parser, which parse template just before > caching templates. Code could be messy HTML or (XHTML) or invalid HTML > (like undisclosed tags, attributes without quotations marks etc.) and > from this make pretty HTML or XHTML according to html coder settings > by {% doctype %} The performance overhead rules out this kind of approach for Django core - any post-processing run against the output of the templates would be executed on every single Django request, and HTML parsing and rewriting is a very expensive operation. That's not to say a third party module couldn't be written to do this kind of thing for people who really want to clean up their output (I remember there being an HTMLTidy middleware a few years back that did this) but it wouldn't be suitable for inclusion in core. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: CSRF - next step?
On Sep 26, 7:44 pm, Alex Gaynorwrote: > So I'm still a little unclear on what this shortcut does that > direct_to_template doesn't already? It's a bit less weird. direct_to_template lives somewhere I can't remember (so I rarely import it), has an argument called "extra_context" that's actually just the regular context, sets up a surprising 'params' key in the context dictionary that contains the function's **kwargs, executes any of the context arguments that are callables before passing them to the template (even though the template language usually does that anyway) and has an argument called mimetype when as-of Django 1.0 content_type is the preferred name for that parameter [1]. direct_to_template is also an odd name - it makes sense for a generic view, but it feels strange when you're using it to render a template from within your view code. Personally, I want a shortcut called django.shortcuts.render which looks like this: def render(request, template, context=None, content_type=DEFAULT_CONTENT_TYPE): return render_to_response(template, context or {}, context_instance=RequestContext(request), mimetype=content_type ) Much less surprising than direct_to_template, and much easier to import. I use this in basically every single one of my view functions so I'd prefer a name that is concise over one that is more descriptive. That's assuming I can't get any buy-in for my TemplateResponse concept[2]. Cheers, Simon [1] (On further inspection it looks like my attempt to get mimetype replaced by content_type throughout Django 1.0 was something of an abject failure, since mimetype is used by both render_to_response and direct_to_template) [2] http://github.com/simonw/django-openid/blob/master/django_openid/response.py - I really like the idea of custom HttpResponse classes that are lazily evaluated just like QuerySets are, but I've got enough stuff to evangelise for 1.2 already ;) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Better HTML4 support
On Sep 26, 10:17 am, Max Battcherwrote: > Furthermore, support for XHTML "5" (which is indeed a part of the HTML 5 > standard) shows that XHTML 1's principles are still around and still > respected. Django's XHTML output can't be "out of date" if XHTML 5 is > considered a successor to XHTML 1. Opinions differ, but in the interest of keeping this thread about HTML support in Django I'm going to leave that discussion here - let's assume that it would be a Good Thing for Django should provide support for outputting both HTML and XHTML, and focus on how we can achieve that. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Better HTML4 support
On Sep 26, 5:48 am, Rob Hudsonwrote: > First, let's not let this turn into an argument about HTML vs XHTML. Oops, sorry! > People have their preference one way or the other, and I believe > Django should be agnostic. Completely agree - that's why I'm in favour of a Django doctype switch rather than a fullscale switch to HTML 5. > django-html Shortcomings: > * Fixes the symptom, not the bug. [1] I think the fix should not do > string replacement, but output the correct HTML in the first place. > (I realize this is the best one can hope for as a 3rd party app, but > if something were to come into core it would have the ability to fix > things properly.) Yes - I looked briefly at how much work was involved in doing this and it's not insubstantial, which is why I opted for string replacement just to demonstrate the API. I'm confident the exact functionality of django-html could be replicated in a less messy way by patching core, but it would require quite a bit of refactoring of django.forms. > * Doesn't "fix" the rest of the areas where Django outputs XHTML. Is > it possible? I think the key problem is template filters, which often produce XHTML (linebreaksbr for example). This could be solved by allowing template filters selective access to the template context, which I'm in favour of in the absence of a compelling argument against. This could be done in a way that allows existing filters to continue to work - maybe something as simple as this: register.filter('cut', cut, takes_context=True) Which emulates the register.inclusion_tag API. > 2. Add a new setting, e.g. settings.DOCTYPE, that various parts of > Django and 3rd party apps use to render HTML. > > Advantages: > * Simple and straightforward > > Shortcomings: > * Yet another setting > * Doesn't allow for template level decisions of doctype by designers Really not keen on that - designers should be able to pick their doctype, and there are some cases where specific pages of a site (or of a reusable app) might need to use a specific doctype - MathML output still requires XHTML for example. I've somewhat foolishly volunteered for a bunch of 1.2 related hacking already (CSRF, logging, signing) but I remain actively interested in this, so I'll try to keep an eye on things and see if there's anything I can contribute. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: Better HTML4 support
On Sep 26, 6:50 am, Jerome Leclanchewrote: > This is a non-issue. Obviously I disagree - this is a tiny thing that has bugged me ever since newforms. It's also something I find myself constantly apologising to front-end developers about, who for the most part love the Django template language. After 9 years In the marketplace, I think XHTML has pretty much lost. It turns out that XML serialisations of HTML aren't nearly as useful as people thought they would be (running an XML parser against the web won't get you anywhere fast, and there are plenty of excellent HTML parsing libraries now), and strict XML error handling is completely unsuitable for the practical considerations of the web. HTML 5 is the final nail in the coffin - the refocusing of the W3C on that over XHTML 2 is an acknowledgement that XML is no longer the future of the Web. I actually think Django's XHTML output makes us look a bit out of date. > Correct me if I'm wrong, but is valid html syntax. It's parsed > as valid by every html parser, and I'm positive this is the entire > point of xhtml: staying backwards-compatible with html. If you want backwards compatibility you need HTML 5, not XHTML. HTML 5 is backwards compatible - it even goes as far as specifying the error handling routines that browsers should take when faced with invalid code (routines that have been reverse-engineered from existing browsers) and properly specifying all of the APIs that browsers support but were never actually part of a specification, such as XMLHttpRequest and innerHTML. XHTML 1.0 is kind-of backwards compatible, but it's a bit of a fudge. It's really meant as a transitional stage between HTML 4 and the stricter XHTML 1.1. As an example of a fudge, the self-closing tags actually mean something different in SGML (HTML's parent language) - they're a short-hand feature called Null End Tags which should technically result in extra > signs appearing in the text, but thankfully no browser actually supports enough of SGML for that to be a problem. The moment you start serving XHTML with the correct content-type (application/xml+html) all sorts of nasty things happen - in addition to strict error handling the way the JavaScript DOM works fundamentally changes - document.getElementsByTagName becomes getElementsByTagNameNS for example. XHTML 1.1 backwards incompatible - the spec forbids the use of the text/html content-type and insists on application/xhtml+xml or application/xml, which breaks completely in IE and causes other browsers to use strict error handling (which you really, really don't want). XHTML 2.0 was completely backwards incompatible (tags were removed, new incompatible tags added), a major factor in the W3C ending official work on it. > That said, I'm not against a {% doctype %} tag or anything. However, I > do think having an xhtml default is a Good Thing due to its backwards > compatibility. I see XHTML as a dead end, so I'd personally prefer to switch to an HTML 5 default - but the {% doctype %} thing makes switching to HTML 5 painless enough that I wouldn't mind the existing XHTML behaviour remaining as the default (purely to avoid causing issues with existing applications). > I'm also not entirely fond of the idea of having 100 > different language outputs in Django. Why stop only after xhtml and > html? Because Django is a Web framework, and XHTML and HTML are the key web languages. I don't think we need to worry about support for those two leading to a slippery slope. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 25, 4:44 pm, Johannes Dollingerwrote: > Regarding parity, let me advertise a Signer object again: > > signer = signed.Signer( > key=settings.SECRET_KEY, > expire_after=3600 > ) > > s = signer.sign(v) > v = signer.unsign(s) > > signer.set_cookie(response, name, value) > signer.get_cookie(request, name) > # or: > signer.get_cookies(request)[name] > > # transparently sign cookies set via response.set_cookie() > # and unsign cookies in request.COOKIES in place: > @signer.sign_cookies > def view0(request): > ... > @signer.sign_cookies('cookie', 'names') > def view1(request): > ... > > This would make more options and customization feasible (by > subclassing): OK, you got me. You obviously know my weakness for customisation by subclassing :) Having a Signer class is a smart idea, I'll kick it around a bit and see how it looks. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 25, 3:39 pm, Simon Willison <si...@simonwillison.net> wrote: > While that makes sense for caching, I couldn't say if it makes sense > for signatures or not - when we sign something, will we always know > the point at which we want that signature to expire? I don't know. Here's a good argument for signing things with the creation-timestamp rather than the expiration-timestamp - it leaves the door open for a mechanism whereby historic SECRET_KEYs are stored. When we see a signed string, we can use its timestamp to decide which of our historic keys should be used to validate it. BIt of an edge case (I can't say if we'd ever want to do this) but it's an example of something that's not possible with expire-at timestamps. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 25, 3:10 pm, Marty Alchinwrote: > The timestamp would then be the actual expiration > time, rather than the time it was signed, so the API can look like > this instead (with a key added per prior discussion). > > >>> s = signed.sign('key', 'value') > >>> v = signed.unsign('key', s) > >>> s = signed.sign('key', 'value', expire_after=24 * 60 * 60) > >>> v = signed.unsign('key', s) Baking an expiration time in to a signed value and checking for it when we unsign is definitely possible, but I'm a bit torn between the two options. I prefer setting the expiry time when I read the cookie rather than when I set it, but I can't say exactly why. I think it's based on bad experiences with memcached - I've frequently found a need to set things in the cache for ever and decide whether or not to treat them as stale on retrieval (for implementing things like serve-stale- on-error) which has made my instinct be to bake the time-of-creation in to the thing and leave the is-this-stale decision until as late as possible. While that makes sense for caching, I couldn't say if it makes sense for signatures or not - when we sign something, will we always know the point at which we want that signature to expire? I don't know. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 25, 1:57 pm, Marty Alchinwrote: > I think this is good for everywhere the raw signing API is accessed, > perhaps to the point where that API can't even be used without a key > (a namespace, really - honking great idea!). Helpers on top of that > API could do without asking for that separately, if they can retrieve > a reasonable key from other forms of input, such as a cookie name or a > query-string argument name. I rather like that idea. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 25, 1:57 pm, Marty Alchinwrote: > I wish there was > a way to sign the expiration as well, so people couldn't artificially > extend the life of the cookie, but since that doesn't come back in the > request, there'd be no way to validate it. We can do that by baking the timestamp the cookie was set in to the signed cookie value, than doing our own check against that and discarding the cookie if it's expired. This pattern (signatures that expire) is common enough that I think it would be worth supporting in the low level django.utils.signed module - I've used timestamped signatures for things like "recover your account" links that expire 24 hours after being requested. The API would look something like this: >>> s = signed.sign('value', timestamp=True) >>> v = signed.unsign(s, expire_after=24 * 60 * 60) A SignatureExpired exception would be raised if the signature was older than the expire_after argument (SignatureExpired would subclass BadSignature) Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 25, 12:02 pm, Luke Plantwrote: > In other web apps (I think Wordpress?), there have been problems > associated with use of secret keys when the same key is used for > different purposes throughout the application. > ... > - we add unique prefixes to the SECRET_KEY for every different > place it is used. So for the e-mail confirmation link, we use > HMAC("email-confirmation" + SECRET_KEY, message) > - also add the ability to do SECRET_KEY rotation, as Simon > suggested. This suggests we want a utility wrapper around hmac > that looks like hmac(unique_key_prefix, key, message) and handles > all the above details for us. I share your concern. In the signed.py module I address your first point by allowing an additional "extra_key" parameter: >>> signed.dumps('hello', extra_key='ultra') 'UydoZWxsbycKcDAKLg.1XYDpILo5xqSwImfa3WuJJT4RPo' >>> signed.loads(_, extra_key='ultra') 'hello' However, this is available on dumps and loads but not on sign and unsign - we should definitely implement it at those points instead. I'm going to ask on some web security mailing list about best practice for rotating keys. Do you have any further information on the WordPress problems? Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 25, 4:48 am, Russell Keith-Mageewrote: > By way of greasing the wheels towards trunk: if the outcome of this > mailing list thread was a wiki page that digested all the ideas, > concerns and issues into a single page, it will make the final > approval process much easier. Great idea: http://code.djangoproject.com/wiki/Signing I've attempted to summarise the discussion so far. I've also added a couple of notes about potential improvements to the proposed django.utils.signed API, in particular a note that having low-level support for signatures that have a timestamp baked in and hence can expire might be a good idea. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 24, 8:22 pm, Benjamin Slavinwrote: > Unfortunately, this approach won't work. > > A malicious client can just send "key" rather than "key__Xsigned" and > you'll never know that the cookie hasn't gone through validation. > This also means that you can't look for cookie values that match a > specific format (ex: body.signature) because a malicious client could > just drop the signature portion. > > As always, we can't trust the client. :-( Good point - that rules that approach out. > 1) request.unsign_cookie('foo') -- This breaks the parallelism with > existing cookies. Sometimes we'll be doing request.COOKIES['foo'] and > sometimes we'll be doing request.unsign_cookie('foo'). If we were going to do that, it would make sense to NOT have set_cookie (... sign=True) as the API for setting one. We could achieve parallelism with something like this: response.sign_cookie('key', 'value') ... value = request.unsign_cookie('key') You can still read request.COOKIES directly, but you'll get the raw, signed value. That API doesn't look too ugly to me. > 2) A decorator for views -- @unsign_cookies("foo", "bar") -- This > doesn't allow any sort of fall-back (you can't customize what to do if > a given cookie is improperly signed) If a cookie is improperly signed I think you silently discard it, as if it was never set. If we had logging this could always be logged as well... we could fire a signal if we really think people might want to further customise it. > 3) COOKIES as an intelligent object -- We can overload .get so we're > doing something like request.COOKIES.get('foo', signed=True) -- I > think this has the best chance at an interface that keeps a consistent > feel. It's completely backward compatible, though it breaks the > traditional expectation of what you can do via the `get` method on a > dictionary. This isn't so bad, since we already have a precedent for this in request.POST.get_list('foo'). request.COOKIES.get_signed(key) might be OK. At the moment I think my preference is for response.sign_cookie and request.unsign_cookie, though I'm a bit worried that "unsign cookie" doesn't obviously mean "get the cookie, check if the signature is OK and return the value if it is". I like that unsign_cookie maps to the low level signed.unsign API, but it might well be that most users never use the low level signing API and the cookie stuff is the only bit of it they ever see. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Adding signing (and signed cookies) to Django core
On Sep 24, 7:37 pm, Marty Alchinwrote: > Another option would be to have request.COOKIES be a custom > dictionary, with an extra .get_unsigned(key) method that would work > like .get(), but validates the signature along the way. That behavior > can't be added straight to __getitem__() though, because that has no > way of knowing whether the cookie was signed to begin with. Hmm... I hadn't considered that. I was thinking that the unsigning could be transparent, so by the time you access request.COOKIES['key'] the value had already been unsigned (and if the signature failed the cookie key just wouldn't be set at all, as if the cookie never existed). But as you point out, this doesn't work because you can't tell if the cookie was signed or not in the first place. We could fix this with a naming convention of some sort: response.set_cookie('key', 'value', sign=True) - results in a Set-Cookie: key__Xsigned=value header But that's pretty ugly. Not sure what to do about this one - request.unsign_cookie('key') might be an option, as at least that reflects the set_cookie / sign / unsign API a bit. Not ideal by a long shot though. > eyes. Yeah, I suppose we could perhaps make that a subclass of > ValueError or TypeError, but I would worry about people wrapping it up > into something else that might cause problems. > > try: > value = signed.unsign(signed_value).decode('utf-8') > except ValueError: > # Whoops! UnicodeDecodeError winds up here as well! That's a great argument against subclassing ValueError - I hadn't considered the unicode case. You're right, if anything it should subclass SuspiciousOperation instead. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Adding signing (and signed cookies) to Django core
As mentioned in the thread about cookie-based notifications, at the DjangoCon Sprints I raised the subject of adding signing (and signed cookies) to Django core. I've found myself using signing more and more over time, and I think it's a concept which is common enough to deserve inclusion in Django - if anything, its use should be actively encouraged by the framework. It's also something that's hard to do correctly. At the sprints Armin pointed out that I should be using hmac, not straight sha1, for generating signatures (something Django itself gets wrong in the few places that implement signing already). Having a cryptographer- approved implementation will save a lot of people from making the same mistakes. Signed cookies == On top of signing (which I imagine would live in django.utils) I'd like to add a signed cookie implementation. Signed cookies are useful for all sorts of things - most importantly, they can be used in place of sessions in many places, which improves performance (and overall scalability) by removing the need to access a persistent session backend on every hit. Set the user's username in a signed cookie and you can display "Logged in as X" messages on every page without any persistence layer calls at all. I think signed cookies should either be a separate API from response.set_cookie or should be provided as an additional argument to that method. I'm not a fan of signing using middleware (as seen in http://code.google.com/p/django-signedcookies/ ) since that approach signs everything - some cookies, such as those used by Google Analytics, need to remain unsigned. So the API could either be: response.set_signed_cookie(key, value) Or... response.set_cookie(key, value, signed=True) (I prefer the latter option) Proposed signing implementation === I'd be happy to donate my signing code from django-openid to the cause, which was written to be usable entirely separately from the rest of the django-openid codebase: http://github.com/simonw/django-openid/blob/master/django_openid/signed.py http://github.com/simonw/django-openid/blob/master/django_openid/tests/signing_tests.py This offers two APIs: sign/unsign and dumps/loads. sign and unsign generate and append signatures to bytestrings and confirm that they have not been tampered with. dumps and loads can be used to create signed pickles of arbitrary Python objects. Here's what the API would look like with this library: >>> from django.utils import signed >>> signed.sign('hello') 'hello.9asVJn9dfv6qLJ_BYObzF7mmH8c' The signature is a URL-safe base64 encoded digest of the hmac/sha1. I used base64 rather than .hexdigest() for space reasons - base64 digests are 27 characters, hexadecimal digests are 40. When you're including signatures in cookies and URLs (especially account recovery URLs sent out in plain text, 80 character wide e-mails) every byte counts. >>> signed.unsign('hello.9asVJn9dfv6qLJ_BYObzF7mmH8c') 'hello' >>> signed.unsign('hello.badsignature') Traceback (most recent call last): ... BadSignature: Signature failed: badsignature BadSignature is a subclass of ValueError, meaning lazy developers (like myself) can do the following rather than importing the exception itself: try: value = signed.unsign(signed_value) except ValueError: return tamper_error_view(request) >>> signed.dumps({"a": "foo"}) 'KGRwMApTJ2EnCnAxClMnZm9vJwpwMgpzLg.mYepoYkzWwXRmsCTVJm3Mb0HHz4' >>> signed.loads(_) {'a': 'foo'} Again, the pickle is URL-safe base64 encoded to take up less valuable cookie space and generally make it easier to pass around on the Web. A nice thing about URL-safe base64 is that it uses 64 out of the 65 URL- safe characters (by URL-safe I mean characters that are left unchanged by Python's urllib.urlencode function) - the remaining character is the period, which I use to separate the pickle from the signature. signed.dumps takes a couple of extra optional arguments. The first is compress=True (default is False) which zlib compresses the pickle if doing so will save any space: >>> import this # to get an object worth compressing ... >>> len(signed.dumps(this.s)) 1207 >>> len(signed.dumps(this.s, compress=True)) 637 By default, all signatures use Django's SECRET_KEY. If you want to sign with a different key, you can pass it as an argument to the various functions: >>> signed.sign('hello', key='sekrit') 'hello.o6MKehoOfZ2b2FU84wzibW6IWxI' >>> signed.unsign(_, key='sekrit') 'hello' The dumps and loads methods also take a key argument, as well as an additional optional extra_key argument for if you want to generate different signatures for different parts of your application (useful for the extra paranoid): >>> signed.dumps('hello', extra_key='ultra') 'UydoZWxsbycKcDAKLg.1XYDpILo5xqSwImfa3WuJJT4RPo' >>> signed.loads(_, extra_key='ultra') 'hello' We'd want to get a proper cryptographer to give this the once-over before adding it to core, but I'm generally happy with
Re: CSRF proposal and patch ready for review
On Sep 22, 9:24 pm, Luke Plantwrote: > > 2. I'm not at all keen on the implementation as a middleware > > (especially a view middleware, which doesn't play well with generic > > views and redispatching to other view functions, both patterns I like > > a lot). > > Could you explain a bit more about the difficulties with generic views? Sorry, I meant to type "class based generic views" - but actually that's not really what I meant either. My problem with view middleware is that it makes it much harder to use the pattern where view functions re-dispatch to other view functions. The classic example is a site with a URL structure that looks like this: /category/sub-category/sub-sub-category/arbitrarily-deep-nesting/news/ I've built stuff like this in the past by essentially discarding urls.py - I instead map "^(.*)$" to my own view function which then splits request.path on slashes and re-dispatches based on its own custom logic. View middleware doesn't really fit that model - it assumes that the top level URL configuration will resolve to the callable that's actually going to implement the view, but that isn't necessarily the case for complex sites. A more common example is view functions which re-dispatch to other functions: def homepage_view(request): if request.user.is_authenticated(): return logged_in_homepage_view(request) else: return default_homepage_view(request) A view middleware will just see "homepage_view" - it won't know which of the actual view functions is going to be called. I'm a big fan of class-based generic views which can involve quite a bit of subclassing and re-dispatching to other methods (like my RestView class http://www.djangosnippets.org/snippets/1071/ ) which is another reason view middleware makes me uncomfortable. Note that this is a philosophical objection to process_view middleware as a whole, not anything specific to CSRF. > 1) Implement your csrf_protect_form method. That could easily add your > requirement to lock down to individual forms and timeouts. It would need > cooperation from a new template tag, or additional optional arguments to the > current template tag. It might also need an additional context processor in > settings, but as an opt-in solution that's OK. > > I think the solution that manipulates request.POST sounds OK - yes a hack, but > providing this method is not the default, most people won't have to deal with > any problems with it. Excellent. I'll have a go at building that against your branch and see how it comes out. > The only question mark in my mind is what happens with multiple forms on a > page (e.g. when you have a login box on every page). It might not be an issue > - the target of the login box will be another view anyway - but it needs > thought. I think that case works OK. It would end up looking something like this: {% csrf_token "login" %} {% csrf_token "rate" %} Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: CSRF proposal and patch ready for review
On Sep 19, 4:56 pm, Russell Keith-Mageewrote: > End users should be allowed to be as lazy as they like, but > their laziness shouldn't open security holes in an app that Django > ships, since the contrib apps (and admin in particular) are the > obvious first port of call for any systematic CSRF attack. > > So - let's have both. A middleware enabled by default protects the > rest of the views. However, we can also have a view decorator lets us > protect admin (and other contrib apps) explicitly. I'm a big +1 for that. > * The SafeForm method of reporting errors as part of form validation > is much nicer than the 403 page, IMHO. However, I'm not sure what we > can do to provide form-level CSRF error handling without introducing a > whole bunch of other fragility. I've been scratching my head over this one - inline error messages and (in particular) not using a form submission are the single thing that makes me favour SafeForm over the template tag approach for my own stuff. That's why I designed SafeForm to complement the forms framework - correctly handling CSRF feels like a form validation problem to me, and reusing Django's redisplay-the-form-with-errors flow is a really neat thing to be able to do. The main reason I really like preserving form data is that it means CSRF failures are less of a problem, allowing us to be much more strict about how they work (setting form tokens to expire after a few hours, tying tokens to individual forms etc). This means we can reduce the damage caused in the case of a token leaking somehow. This becomes particularly important if tokens are going to be used to protect GET requests, which some applications may want to do (Flickr have CSRF- protected GETs for their logout and change-language links, for example) - GET tokens are more likely to leak in other people's referrer logs or to intermediate proxies. There is a way we could achieve form validation, but it isn't particularly pretty. Say the CSRF check is performed by a decorator (which has an accompanying middleware for applying that decorator to the entire site). The problem we have is that in the case of a failure, the fact that the check failed needs to be communicated through to the form /inside/ that view. The form doesn't have access to the request, so we're stuck. But... the form does have access to request.POST. The dirty solution would be for the decorator to rewrite request.POST to include a new key: request.POST.mutable = True request.POST['__validation_must_fail'] = True request.POST.mutable = False django.forms.Form.is_valid() could then be hard-coded to always fail if '__validation_must_fail' is present in the data dictionary. I've avoided including the string "csrf" in the form key because this feature feels like it could be useful for other things as well (I might use it for testing out my form error styles). I don't think it's a security vulnerability - if someone fakes a "__validation_must_fail" key in their own submission I don't see that there's anything bad they can do. It's a pretty monstrous hack, but it would allow a CSRF protecting decorator to inform a form inside a view that the check had failed and the form should not validate. I wouldn't suggest this as the default behaviour for the overall CSRF protection scheme - it would leave hand-rolled forms unprotected, and I imagine there are new error cases it would introduce. That said, it would placate users like myself who want the nicer invalidation messages and are willing to do a bit of work to achieve them. Maybe something like this: @csrf_protect def view(request): """A view that fails the CSRF check with a full page 403, as seen in Luke's current middleware""" @csrf_protect_form def view(request): """A view that won't 403 directly, but will ensure that any calls to form.is_valid() fail due to the presence of a __validation_must_fail key""" Thinking more pie-in-the-sky-ly, maybe this approach could be generalised further, to specify a mechanism by which request.POST can include a set of validation errors that should be shown by the form. This might have other uses in things like wizards where validation errors may want to persist between different pages. > * The requirement for using RequestContext is somewhat annoying. I > can't see any obvious way to piggyback CSRF data onto the base Context > itself, but perhaps we can make RequestContext a more prominent > default? The most obvious solution here is to make render_to_response > use RequestContext by default. Yes, yes and thrice yes - my only complaint about RequestContext is how horrible the syntax for using it is: render_to_response('template.html', { 'name': 'Foo', 'blah': 'baoenuth', }, context_instance=RequestContext(request)) Yeah, I'd like a builtin shortcut like that - used like this: render(request, 'template_name.html', {'foo':bar }) The biggest problem, for me, is finding a decent name - since
Re: CSRF proposal and patch ready for review
On Sep 18, 12:09 am, Luke Plantwrote: > OK, here is my response. I hope this doesn't turn into a personal my-code-vs- > your-code match (especially as most of "my code" is really other people's code > and ideas :-) but I want to make sure we do this right, as it potentially has > big implications, so the following will be "sleeves rolled up" (getting into > details) and "gloves off" when it comes to criticisms of the code itself :-) Completely up for that - this is really excellent stuff. Django needs the best possible solution for this problem, so the more smart discussion around it the better. > Advantages of SafeForm > -- > > I can see the value of having contrib apps secured whatever the user has in > their settings.py > > Unfortunately, that is the only advantage of any significance that I can > see. There are a couple of other advantages that I haven't document anywhere: 1. SafeForm has no dependency on Django's session framework. This is A Good Thing as I personally avoid sessions in my projects (no need to access state on every request if you can get away with not doing it). 2. SafeForm fails relatively gracefully in the event of CSRF check failures - since it's tied in to the form validation flow, it displays an inline error message but you don't lose your form data. This is my personal favourite characteristic of SafeForm, partly because it allows you to be much more strict with your CSRF tokens - you can create tokens that expire relatively quickly without risking too much harm to your users. > Disadvantages of SafeForm > - > > 1) Big changes are required to use it. Yes, very true. The form tag / RequestContext solution is a major improvement there. > * quite commonly, significant changes to the template: > * Often you have to explicitly add the csrf token field. And you've > got to worry about whether you need to or not. Thankfully if you do add it when it's not needed nothing bad happens - Django silently blanks out {{ form.csrf_token }} (I've complained about this before but here it's actually useful). > * If you weren't displaying form.non_field_errors before (which can be > common if you don't need it), you have to add it. Again, this actually isn't too bad - if you forget to add non_field_errors, you'll just lose the CSRF validation message - your form will still preserve data and can be resubmitted. I noticed Flickr fail silently like that if you fail a CSRF check (by tampering with their magic_cookie) - they simply redisplay the form with your data filled in, without any kind of error message. > 2) More than one way to do CSRF protection. > > Although you provide a low level mechanism for forms, it still means you have > Two Ways To Do CSRF Protection, and they are quite different (from the users > point of view). Once you've added in the multiple forms in a problem, > you've now got Three Ways To Do CSRF Protection, all of which will be needed > in quite common circumstances. I count Four Ways - I see no reason to remove the Django 1.1 middleware method, which is a convenient way of adding CSRF protection to an entire site, even if it's a bit ugly. Adding a new CSRF protection mechanism is likely to significantly increase awareness of the issue whatever we do, so I wouldn't be surprised to see a lot of people start turning on the old middleware as a stop-gap measure. So yes, this isn't exactly ideal. > 3) More than one way to do Forms > ... > Every user now faces a choice - use Form or SafeForm? Form seems to be > simpler; the API is possible to play with at the interactive prompt (see > tests/regressiontests/forms.py, for example), unlike SafeForm which requires > an HttpRequest object; and SafeForm sounds like something for the paranoid, > ultra-secure types. So you can bet that tutorials and code across the > internet are going to use Form. I dunno, this feels like something that can be mostly addressed with documentation and community pressure. I'm perfectly willing to spend the next year explaining CSRF to anyone who cares to hear about it - it's shocking how poorly understood it is within the industry as a whole. > Because they have switched to using SafeForm, that form will now > include the CSRF token, which is leaked to external sites, which is a security > vulnerability. I'm not enormously worried about this one - again, I don't feel we'll be able to solve the CSRF problem without some serious end-user education. If we're really worried about this we could set the default token expiry time to half an hour to at least limit the potential damage a bit. (I know end-user education is rarely the answer to anything, but at least we're dealing with developers here). > 4) CSRF is baked in to view functions. > ... > * Developers can't 'swap out' the implementation of CSRF protection. With > the template tag method, this is easy to do. If someone has custom >
Re: CSRF proposal and patch ready for review
On Sep 17, 3:42 pm, Simon Willison <si...@simonwillison.net> wrote: > All good points - the change in function signature naturally fell out > of the CSRF work (since the form needs access to the request object in > both cases) but you've convinced me that it's a step too far - I'll > see if I can fix that. I just pushed a new release which changes the constructor signature back to the way it works in regular Django: http://pypi.python.org/pypi/django-safeform/2.0.0 (Really should have used 0.1 / 0.2 etc for the version numbers, lesson learnt for next time!) I also added some unit testing sugar to address one of Luke's (many) points, see the "Unit testing" section of the README file. I'm still digesting the rest of his e-mail, plenty to think about there. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
On Sep 18, 6:21 pm, Eric Holscherwrote: > I have looked into Logging before for another project, and I found that > SQLAlchemy's support seemed to be a pretty good model to follow. They define > all of their loggers under the sqlalchemy namespace, and then you can > configure different handlers for different things[1]: > > I think that this would be necessary to have in Django, so that for > instance, I could listen to the django.orm logs, and not the django.http, or > listen to them with different handlers/levels. Yes, absolutely - this looks like exactly the right model. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal for 1.2: built-in logging with django.core.log
On Sep 17, 4:04 pm, Russell Keith-Mageewrote: > I've seen several attempts to wrap Java loggers in a "nicer" > interface, and every one of them ended up hobbling some of the power > features of the logger. There is also the issue of our wrapper playing > nicely with the loggers already being used in the wild. I should clarify - by "lightweight wrapper" I basically mean a pre- configured log setup and a standard place to import the logger from - and maybe a tiny bit of syntactic sugar if it will make the common case more palatable. I'm mostly just interested in making the logging module an encouraged technique within the Django world. It should definitely play nicely with any already-existant logging code. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: CSRF proposal and patch ready for review
All good points - the change in function signature naturally fell out of the CSRF work (since the form needs access to the request object in both cases) but you've convinced me that it's a step too far - I'll see if I can fix that. Cheers, Simon On Sep 17, 2:10 pm, Russell Keith-Magee <freakboy3...@gmail.com> wrote: > On Thu, Sep 17, 2009 at 3:11 PM, Simon Willison <si...@simonwillison.net> > wrote: > > > On Sep 15, 2:57 pm, Luke Plant <l.plant...@cantab.net> wrote: > >> OK, I'll wait and see. > > > Here's the code:http://github.com/simonw/django-safeform > > >> * it requires using Django's form system. I've got plenty of views that > >> don't (e.g. anything with a dynamic number of controls). People not using > >> django.Forms are left out in the cold, or having to learn another way to do > >> things. > > > I've covered this in django-safeform by exposing a low level interface > > to the CSRF token creation and validation routines (in csrf_utils) - > > see the readme for documentation on this. > > >> * it's off by default. Turning it on by default will require making > >> django.forms.Form subclass SafeForm, which will almost certainly require a > >> huge and immediate upgrade effort, because SafeForm cannot have the same > >> API > >> as Form. If it's off by default, I see no point at all in this entire > >> exercise. If we don't arrive at a point where the POST form created in the > >> tutorial is safe from CSRF, I think we've failed. > > > My priority for this is a little different: while I would dearly love > > to see all Django applications secure against CSRF by default, I can't > > see a way of doing it that doesn't break existing apps. More important > > for me though is that the Django admin (and other reusable apps, such > > as Pinax stuff) MUST be secure against CSRF out of the box, no matter > > what the user puts in their settings.py file. If developers fail to > > protect themselves (especially when the solution is well documented) > > then at least it isn't our fault. > > > I think this is subtly different from the XSS escaping issue simply > > because the solution to CSRF is much more intrusive. > > >> And it will still require changes to templates, just like the template tag, > >> and it will also require changes to views, only significantly more complex > >> than simply using RequestContext. It's got at least as many and at least > >> as > >> intrusive 'moving parts' AFAICS. > > > The SafeForm API actually simplifies views - you go from this: > > > def change_password(request): > > form = ChangePasswordForm() > > if request.method == 'POST': > > form = ChangePasswordForm(request.POST) > > if form.is_valid(): > > return HttpResponse('Thank you') > > return render_to_response('change_password.html', { > > 'form': form, > > }) > > > To this: > > > @csrf_protect > > def change_password(request): > > form = ChangePasswordForm(request) > > if form.is_valid(): > > return HttpResponse('Thank you') > > return render_to_response('change_password.html', { > > 'form': form, > > }) > > > The SafeForm deals with the request.method == 'POST' bit, meaning one > > less conditional branch within the view function itself. > > Did we discuss this bit at the sprint? I'm completely on board with > everything else, but this bit makes me nervous: > > * It calls is_valid() on the form during a GET (which isn't currently > done as part of normal practice). > > * It isn't possible to have any special view handling based on the > request method. > > * It implies that the method of construction the form will always be > the same, regardless of whether we are GETting or POSTing. This isn't > always true - in particular, I'm thinking of the construction of > FormSets, which can use a queryset to populate the forms on GET, but > don't require the queryset on POST. > > > I'm pretty happy with the SafeForm interface now that I've fleshed it > > out - it's a lot less clunky than I was originally expecting. > > Another advantage that Simon hasn't mentioned - it requires no > modifications to the tutorial. We can present the basic ideas of form > handling in tutorial 4 without mentioning CSRF. We then have scope to > introduce a new tutorial on security issues, that can both educate on > the nature of XSS and CSRF attacks, plus what you have to do in order > to protect against them. > > Yours, > Russ Magee %-) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Replacing get_absolute_url, I am against it
On Sep 15, 12:04 pm, Ivan Sagalaevwrote: > James Bennett wrote: > > Except I can't help thinking this is an awfully arbitrary distinction > > to draw. In effect you're saying that nearly every question about an > > object should be answerable by interrogating it directly, *except* for > > "what's a URL I can use for you?" > > May be I can explain this distinction with an example. > > We once had two different web sites about "events". They both had a > "core" set of models but each one had their own set of views & urls. So > for a core Event model a question "what's your URL" just didn't make > sense. It had two different URLs depending on the project it was > imported in. For me, this one boils down to pragmatism v.s. purity. >From a purity point of view, having models that know what their URLs are when Django's concept of a URL is defined in the urls.py file is an obvious violation of separation of concerns. >From a pragmatism point of view, being able to ask an object it's URL is incredibly convenient - and in 90% of the projects I've worked on in the past few years each object has had one and only one URL (in fact REST principles actively encourage this). I'm OK with .get_url() and .get_url_path() (I still prefer the semantics and names used in my original proposal to any of the proposed alternatives) only being useful 90% of the times, with projects where objects can have more than one URL needing to find some alternative method. As for running code, allow me to point to http://code.google.com/p/django-urls/ :) Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: SoC merge plans?
On Sep 13, 12:52 pm, Russell Keith-Mageewrote: > Although the branch isn't ready for merge yet, the code that is > present is all up to spec. I think the sprints have produced workable > solutions for the outstanding problems; fixes implementing the > solutions we discussed should be forthcoming shortly. With my cowboy hat on... what are the disadvantages to merging this to trunk /now/ and fixing the remaining outstanding issues there? It might make it easier to get the other SoC branches compatible with this one (which sounds to me like it makes the most far-reaching changes) and it would encourage the wider community to help check that everything really is backwards compatible. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Proposal for 1.2: built-in logging with django.core.log
I think we should add logging to Django in version 1.2, implemented as a light-weight wrapper around the Python logging module (django.core.log maybe?) plus code to write errors to the Apache error log under the mod_python handler and environ['wsgi.errors'] under WSGI (meaning mod_wsgi will write to the Apache error log as well). Benefits of logging as a core Django service Adding logging to Django core would provide the following benefits: 1. We'll be able to de-emphasise the current default "e-mail all errors to someone" behaviour, which doesn't scale at all well. 2. Having logging in the core framework will mean people start actually using it, which will make it easier for people to debug their Django apps. Right now adding "print" statements to a Django app is a common debugging technique, but it's messy (you have to remember to take them out again) and error prone - some production environments throw errors if an app attempts to write to stdout. It's also not obvious - many developers are surprised when I show them the technique. 3. Logging in Django core rather than a 3rd party app will encourage reusable applications to log things in a predictable way, standard way. 4. 3rd party debugging tools such as the debug toolbar will be able to hook in to Django's default logging behaviour. This could also lead to plenty of additional 3rd party innovation - imagine a tool that looks out for logged SQL that took longer than X seconds, or one that groups together similar log messages, or streams log messages to IRC... 5. Built-in support for logging reflects a growing reality of modern Web development: more and more sites have interfaces with external web service APIs, meaning there are plenty of things that could go wrong that are outside the control of the developer. Failing gracefully and logging what happened is the best way to deal with 3rd party problems - much better than throwing a 500 and leaving no record of what went wrong. 6. Most importantly from my point of view, when a sysadmin asks where Django logs errors in production we'll have a good answer for them! 7. As a general rule, I believe you can never have too much information about what's going on with your web application. I've never thought to myself "the problem with this bug is I've got too much information about it". As for large log files, disk space is cheap - and pluggable backends could ensure logs were sensibly rotated. Places logging would be useful == - Unhandled exceptions that make it up to the top of the Django stack (and would cause a 500 error to be returned in production) - The development web server could use logging for showing processed requests (where currently these are just printed to stdout). - Failed attempts at signing in to the admin could be logged, making security audits easier. - We could replace (or complement) django.connection.queries with a log of executed SQL. This would make the answer to the common question "how do I see what SQL is being executed" much more obvious. - Stuff that loads things from INSTALLED_APPS could log what is being loaded, making it much easier to spot and debug errors caused by code being incorrectly loaded. - Likewise, the template engine could log which templates are being loaded from where, making it easier to debug problems stemming from an incorrectly configured TEMPLATE_DIRS setting. - We could use logging to address the problems with the template engine failing silently - maybe some template errors (the ones more likely to be accidental than just people relying on the fail-silent behaviour deliberately) should be logged as warnings. Most of the above would be set to a low log level which by default would not be handled, displayed or stored anywhere (logging.info or similar). Maybe "./manage.py runserver --loglevel=info" could cause such logs to be printed to the terminal while the development server is running. Problems and challenges === 1. The Python logging module isn't very nicely designed - its Java heritage shines through, and things like logging.basicConfig behave in unintuitive ways (if you call basicConfig twice the second call fails silently but has no effect). This is why I suggest wrapping it in our own higher level interface. 2. There may be some performance overhead, especially if we replace mechanisms like django.connection.queries with logging. This should be negligble: here's a simple benchmark: # ("hello " * 100) gives a 600 char string, long enough for a SQL statement >>> import timeit, logging >>> t = timeit.Timer('logging.info("hello " * 100)', 'import logging') >>> t.timeit(number=100) # one hundred statements 0.00061702728271484375 >>> t.timeit(number=100) # one million statements 6.458014965057373 That's 0.0006 of a second overhead for a page logging 100 SQL statements. The performance overhead will go up if you attach a handler, but that's
Re: CSRF proposal and patch ready for review
On Sep 15, 2:57 pm, Luke Plantwrote: > OK, I'll wait and see. Here's the code: http://github.com/simonw/django-safeform > * it requires using Django's form system. I've got plenty of views that > don't (e.g. anything with a dynamic number of controls). People not using > django.Forms are left out in the cold, or having to learn another way to do > things. I've covered this in django-safeform by exposing a low level interface to the CSRF token creation and validation routines (in csrf_utils) - see the readme for documentation on this. > * it's off by default. Turning it on by default will require making > django.forms.Form subclass SafeForm, which will almost certainly require a > huge and immediate upgrade effort, because SafeForm cannot have the same API > as Form. If it's off by default, I see no point at all in this entire > exercise. If we don't arrive at a point where the POST form created in the > tutorial is safe from CSRF, I think we've failed. My priority for this is a little different: while I would dearly love to see all Django applications secure against CSRF by default, I can't see a way of doing it that doesn't break existing apps. More important for me though is that the Django admin (and other reusable apps, such as Pinax stuff) MUST be secure against CSRF out of the box, no matter what the user puts in their settings.py file. If developers fail to protect themselves (especially when the solution is well documented) then at least it isn't our fault. I think this is subtly different from the XSS escaping issue simply because the solution to CSRF is much more intrusive. > And it will still require changes to templates, just like the template tag, > and it will also require changes to views, only significantly more complex > than simply using RequestContext. It's got at least as many and at least as > intrusive 'moving parts' AFAICS. The SafeForm API actually simplifies views - you go from this: def change_password(request): form = ChangePasswordForm() if request.method == 'POST': form = ChangePasswordForm(request.POST) if form.is_valid(): return HttpResponse('Thank you') return render_to_response('change_password.html', { 'form': form, }) To this: @csrf_protect def change_password(request): form = ChangePasswordForm(request) if form.is_valid(): return HttpResponse('Thank you') return render_to_response('change_password.html', { 'form': form, }) The SafeForm deals with the request.method == 'POST' bit, meaning one less conditional branch within the view function itself. I'm pretty happy with the SafeForm interface now that I've fleshed it out - it's a lot less clunky than I was originally expecting. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Long-term direction for shortcuts
On Aug 3, 3:53 am, chairfacewrote: > Also, it is only a single video, but that video > is a pretty good resource for the topic of Django's future. It was > the topic of the entire hour. Are you implying that it's a poor > source for people wondering where Django is going? It was explicitly > designed to be exactly that kind of source. I'm sorry if I gave that impression, but it really wasn't my intention. The talk was titled "Django Heresies" partly because I wanted to emphasize that it was NOT a discussion of Django's intended future - it was more an exploration of things which one person (me) thought we should reconsider as a community and open up for further discussion. It was meant to be controversial! > Simon has not justified why his particular preference for imports > necessarily meets even the common case and why he, or somebody else, > cannot put their own choices for common imports into a single that they > import (pretty normal "reduce repetition" pattern in Python). All I was saying is that I find myself repeating the same imports at the top of every views.py - and wondering if there's a better option. For my own projects I inevitably end up creating my own shortcuts.py module. I wish I didn't have to. As an aside, I've been experimenting with the single import pattern (which I rather like, but everyone else seems to hate) in djng: http://github.com/simonw/djng/blob/953eb33390972cbdd0ac0a52e3b23bfdd55e2cfe/example_forms.py Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Multi-DB Update
On May 2, 12:19 am, Malcolm Tredinnickwrote: > I'd prefer dictionaries to strings, because strings are tough to modify > dynamically -- as has already been demonstrated a few times in Django's > history. That's a pretty strong argument in favour of dictionaries - in which case it might be good to switch the CACHE_BACKEND setting over to using dictionaries instead of a DSN-style string at some point in the future - consistency seems like it would be a good thing here. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Multi-DB
On Apr 30, 12:25 am, Alex Gaynorwrote: > My question would be how is using a DSN and letting those be passed directly > to using() any advantage over letting someone pass a dict of those options > to using(), or a connection object itself. No advantage at all - I'm interested in being able to hand a dynamically constructed connection to using(), and I don't particularly mind if it's a DSN, a dictionary or a connection object I've created already. My principle arguments for DSNs are the other two - we already use them for cache backends, and it's what SQLObject and SQLAlchemy do. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Multi-DB
On Apr 25, 7:11 am, Alex Gaynorwrote: > Simon uses a new DSN based syntax for specifying DBs, however I find this > pretty akward in the presence of our existing way for defining DB settings. I had a few reasons for suggesting DSNs: * We already use DSN-style syntax for cache backends - it's weird to do it there (for something that isn't actually a database) but not for our database settings. Of course, that inconsistency could be fixed by splitting up the settings for cache backends instead. * SQLObject and SQLAchemy both use DSNs. * If we implement my suggestion that a using() method can take a connection object OR a connection alias string (defined in settings.py) OR a DSN, it's much easier to dynamically construct a database connection at runtime. I'm particularly interested in that last usage scenario. Personally I'm not a big fan of settings.py - over the past four years I've found myself at various times wanting to dynamically alter almost every setting in there - and there are some interesting edge cases where creating a database connection at run time could be useful. Three off the top of my head: 1. A phpMyAdmin style application for administering remote databases, which might allow the user to enter their database details in to an online form 2. A web-based installation mechanism, such as the one used by WordPress 3. (really nutty one this) - a very high scale situation where an application is partitioned across hundreds of databases, which each one having the same set of tables. This is how WordPress-MU works (as used by wordpress.com), with every blog getting its own duplicate set of tables - and it's surprisingly effective. Creating a database connection at runtime doesn't require DSNs of course, provided you can feed your own connection object to any using () clause rather than being tied to using connections that have already been configured in settings.py. > Further a DSN method removes the presence of something like > DATABASE_OPTIONS(unless we start adding query strings onto the end), which > is very useful for things like the postgresql auto commit option, plus I > plan to move the TEST_DATABSE_* settings into DATABASE_OPTIONS, since things > like charset are DB dependent. Again, we use query strings for cache backends so I have no problem with using them for database options. I wouldn't be heartbroken if DSNs weren't used in Django, but the above should at least explain the reasons behind my suggestion. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 24, 2:18 pm, zellyn <[EMAIL PROTECTED]> wrote: > Would it make sense to have the middleware/view decorator set a > property on the request, and pass the request to all forms, and have > *all* forms CSRF-protect themselves when the property is set? That > would make it easy to add protection to externally-developed apps. That's an interesting idea. I'm a bit cautious of requiring ALL forms to take a request object though - Django's current form library is decoupled from Django's request object, which is actually a really useful property. I've used a "form" class to import CSV data in to Django ORM models in the past for example, using the form logic to handle the necessary type conversions. Keeping django.forms decoupled from HttpRequest also ensurse it can be used by other Python web frameworks that don't have the same request/ response model. I'm fine with SafeForm depending on HttpRequest, but I'd rather not introduce that dependency to BaseForm and Form. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Inner imports in core code
On Sep 24, 1:40 pm, Simon Willison <[EMAIL PROTECTED]> wrote: > As a result the performance overhead from having imports inside > functions as opposed to at module level should be virtually non- > existent. Not entirely sure how I managed to miss your benchmark figures when I read your mail, but I'm wrong here - there's clearly a performance overhead involved in importing inside a function. It would be interesting to see how much this affects Django performance as a whole - I guess this is the kind of question the proposed metronome benchmark will help answer. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Inner imports in core code
On Sep 24, 8:37 am, David Cramer <[EMAIL PROTECTED]> wrote: > I was digging through some code today, and I noticed imports are > happening within a lot of functions. It was my knowledge that it works > like so: > > import in a function is the same as ruby's load or php's include -- > its executed everytime the function is > > import in a module outside a function is like ruby's require or php's > require_once -- its loaded and cached in memory That's not the case. Try the following: # importme.py print "running importme" def three(): print "3 - from importme" # test1.py import importme importme.three() # test2.py def one(): import importme print "1" importme.three() def two(): import importme print "2" importme.three() one() two() $ python test1.py running importme 3 - from importme $ python test2.py running importme 1 3 - from importme 2 3 - from importme As you can see, the initial print statement in importme.py only executes once, even when "import importme" is run twice (from inside functions). As I understand it, Python's "import" statement checks sys.modules to see if something has been imported already. If it hasn't, the module is loaded for the first time and executed. If it has already been imported (and hence is in sys.modules) then no extra code is loaded or executed - the import statement merely ensures that a reference to that module is available in the function's scope. As a result the performance overhead from having imports inside functions as opposed to at module level should be virtually non- existent. I don't think we need to worry about this - and like Jeremy said, usually there's a reason for doing it (avoiding importing something unless it's actually going to be needed, or avoiding circular imports). Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 23, 11:23 pm, Simon Willison <[EMAIL PROTECTED]> wrote: > CSRF attacks are a problem for systems where an action is only meant > to be available to a specific logged in user. This user is inevitably > identified by a unique cookie. This is normally a session cookie, > hence many CSRF protection mechanisms key their hidden form token off > the session cookie. It turns out it's not that straight-forward after all: http://icanhaz.com/csrfpdf (PDF link, "Robust Defenses for Cross-Site Request Forgery") The above paper introduces the "login CSRF" attack, where CSRF is used to force a victim to log in to a site using /the attacker's/ credentials. The hope is that the user will then enter personally sensitive information which the hacker can harvest later on. Django's CSRF mechanism needs to be able to protect forms even in the absence of a unique-to-the-user cookie, which means it needs a way of setting its own cookies. We can either do this using the form.protect() or form.render_response() methods I advocated earlier, or we can use a middleware/view decorator combination. I think I'm leaning towards the view decorator / middleware option now. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 23, 11:51 pm, "Amit Upadhyay" <[EMAIL PROTECTED]> wrote: > There is another option, a template tag. I would implement it as a > middleware and a template tag. Template tag csrf_protect, will require > CSRFMiddleware and django.core.context_processors.request, will add a > input file containing something derived from {{ request }} and > middleware will check and raise HttpForbidden. Oddly enough that's exactly how ASP.NET MVC does it: http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/ They use their equivalent of a view decorator rather than middleware, which is what I'd suggest doing in this case as well (middleware in Django is usually applied globally which isn't always what you want). Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 24, 1:04 am, Simon Willison <[EMAIL PROTECTED]> wrote: > There's another option that avoids the need for any cookies at all: > generating a persistent one-use-only token when a form is saved, > storing that in the database and only allowing submissions that > include a token that was previously assigned. Scratch that - the tokens would still need to be assigned to an individual user (almost certainly keyed off a cookie) as otherwise an attacker could create their own tokens and use them to attack another user. It would work for sites protected using HTTP authentication rather than cookies though, as you'd be able to attach each token to the HTTP auth username. I don't think this is a case we need to address though. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 23, 11:23 pm, Simon Willison <[EMAIL PROTECTED]> wrote: > CSRF attacks are a problem for systems where an action is only meant > to be available to a specific logged in user. This user is inevitably > identified by a unique cookie. This is normally a session cookie, > hence many CSRF protection mechanisms key their hidden form token off > the session cookie. There's another option that avoids the need for any cookies at all: generating a persistent one-use-only token when a form is saved, storing that in the database and only allowing submissions that include a token that was previously assigned. This avoids any need for cookies at all, but has the serious disadvantage that you end up with potentially thousands of useless tokens stored in your database. You can clear these out periodically but it's still overhead that it would be nice to avoid. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 23, 1:06 am, Simon Willison <[EMAIL PROTECTED]> wrote: > Since all form.protect(response) actually does is ensure that there's > a csrf cookie, you should only actually have to do it once for one of > the forms. Unsurprisingly, I've been totally over-engineering this. There's no need for form.protect(response) at all - in fact, the form doesn't need to have anything to do with the response object. This dramatically simplifies things - in fact, it takes us back to the original proposal of a SafeForm that just takes the request object as an argument to its constructor. CSRF attacks are a problem for systems where an action is only meant to be available to a specific logged in user. This user is inevitably identified by a unique cookie. This is normally a session cookie, hence many CSRF protection mechanisms key their hidden form token off the session cookie. That's also what Django's CSRF middleware does. I like to be able to avoid sessions where possible, which is why I didn't want SafeForm to use the session cookie and thought it would need to set a cookie itself. But even if an application isn't using sessions, it's still going to need to use one or more cookies that are unique to the user. I think we solve this with a setting, the default of which looks like this: CSRF_COOKIES = [SESSION_COOKIE_NAME] SafeForm creates its csrf_token based on a hash of the cookie values for the keys in that list. It's a list because some authentication cases may rely on more than one cookie to uniquely identify the user (rare but possible). By default, it will use the Django session cookie. If you're not using sessions in your app (you're using a signed cookie called 'current_user' for example) you can specify that in the CSRF_COOKIES session. So, the bit about the SafeForm needing access to the response was a red herring. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 23, 10:17 pm, "Robert Coup" <[EMAIL PROTECTED]> wrote: > then when you get a form submission, base64-decode it, split at "/", check > the hash matches by recalculating it, then use the proximity-to-timestamp > and the remote_addr to check the form validity. Anything that relies on remote_addr is flawed, because IP addresses change all the time. I frequently load up a Google Groups thread on my laptop, compose a reply on the train to work and submit it when I get there - and since I've moved networks my IP address changes in between loading the form and submitting it. There's also the risk of proxies that load balance traffic through different IP addresses, not to mention IP addresses that are shared by many people (including a potential attacker). Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Denormalisation, magic, and is it really that useful?
On Sep 23, 2:00 pm, "Marty Alchin" <[EMAIL PROTECTED]> wrote: > Without some Python-based approach, all I could see is maybe adding a > cross-platform "create trigger" API (ugh) to Django, which an > application could then use to set up its triggers during syncdb. > Otherwise, something like that forum app would have to implement a > trigger for all available backends or just ship with instructions on > how to set it up yourself. Triggers also aren't supported in Drizzle ( https://launchpad.net/drizzle ), which Django will probably want to target at some point. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 23, 9:00 am, oggie rob <[EMAIL PROTECTED]> wrote: > I just read this thread now, and by the end of it, things are looking > pretty complicated. Is it worth a gut check to make sure this is > worthwhile? Although the middleware might be a hack now, it seems > sensible that it fits in request/response areas rather than in forms: > you still need to go out of your way to add it anyway (so users won't > necessarily "turn it on"); it takes a lot more code; add in the > multiple forms per page question, and to me it seems like you've fixed > a problem by introducing another. Here's a useful case in point: the admin. Django's admin should ship with CSRF protection turned on and baked in. Right now, I'm willing to bet 95% of the Django admin sites out there are exploitable via CSRF because the middleware wasn't turned on. This is really bad. I'm positive we can figure out a better API for CSRF protection than what we have at the moment. At the moment I'm focused on forms, but if there's something we can do at the view level instead I'd love to see some suggestions. > Finally, it doesn't take much to make a pretty message - something > like "You are under attack, close down your browser and try again" > with images of flaming people & such - for the (lets be realistic) > very rare cases when a CSRF attack occurs. I'm worried about false positives. One example where this would happen is if you were to change your SECRET_KEY (secret management is a whole other issue we haven't addressed). That's why I like the validation error approach - it's unobtrusive and doesn't unnecessarily scare people. We should definitely log detected CSRF issues though (logging = another issue). Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 23, 12:53 am, Tai Lee <[EMAIL PROTECTED]> wrote: > On Sep 23, 9:27 am, Simon Willison <[EMAIL PROTECTED]> wrote: > > > The significant downside is that having a render() method on a form > > that performs the same function as render_to_response feels really, > > really strange. It's convenient, but it just doesn't feel right and > > I'm not sure I can justify it. > > How would this work when you have multiple forms/modelforms/formsets > on one page? In that case, you'd have to fall back to the old way of doing things - form.render() would be a shortcut, not the only way of doing this. You'd probably end up with code that looked like this: def complex_view(request): form_one = FormOne(request) form_two = FormTwo(request) form_three = FormThree(request) if form_one.is_valid() and form_two.is_valid() and form_three.is_valid(): # Do something with their cleaned_data return HttpResponseRedirect("/done/") response = render_to_response('complex_view.html', { 'form_one': form_one, 'form_two': form_two, 'form_three': form_three }) form_one.protect(response) form_two.protect(response) form_three.protect(response) return response Since all form.protect(response) actually does is ensure that there's a csrf cookie, you should only actually have to do it once for one of the forms. Maybe it shouldn't be a form method at all in that case - maybe it should be a function called django.forms.protect(request, response) (request so it can check if the cookie has been set already, and response so it can set it if needed). Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Denormalisation, magic, and is it really that useful?
On Sep 23, 12:21 am, "Justin Fagnani" <[EMAIL PROTECTED]> wrote: > In my experience at least, denormalization occurs > a lot and leaves a lot of room for mistakes, so it's something a > framework should handle if possible. Just so it's on the record, I'd like any denormalisation tools in Django to include a mechanism for re-syncronizing them should something go awry (like direct updates being applied to the database without keeping the denormalised fields in sync). This mechanism could then be exposed as a ./manage.py command which could be called periodically to verify and fix any incorrect data. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 23, 12:27 am, Simon Willison <[EMAIL PROTECTED]> wrote: > return form.render('add_article.html', { > 'extra_context_args': 'Go here', > }) Using render_response as the method name might make this a little more palatable: return form.render_response('add_article.html', { 'extra_context_args': 'Go here', }) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 22, 9:41 pm, Brian Beck <[EMAIL PROTECTED]> wrote: > - If there's some other way to spell form.protect(response). Here's a crazy idea that might just work: class AddArticleForm(forms.SafeForm): headline = forms.CharField() # ... def add_article(request): form = AddArticleForm(request) if form.is_valid(): # Process the data in form.cleaned_data return HttpResponseRedirect('/done/') return form.render('add_article.html', { 'extra_context_args': 'Go here', }) We're doing a bunch of interesting things here. First, it's AddArticleForm.__init__ itself that looks at request.method and decides if it's going to bind to the data (if request.method == 'POST') or simply create a new blank form. Second, we're using form.render() instead of render_to_response. form.render is a thin wrapper around render_to_response that does the following: 1. Adds 'form' to the context - a "form_var='article_form'" keyword argument could be used to change this default behaviour 2. Uses a RequestContext (with the request that was passed to AddArticleForm.__init__) - I can't think of any reason not to 3. Creates the HttpResponse using render_to_response 4. Sets a CSRF cookie on the response, if necessary This solves all of our problems in one shot (the need to sometimes set a cookie, having access to the request, etc), with the added bonus of reducing the amount of view boilerplate needed to use a form to the absolute minimum. The significant downside is that having a render() method on a form that performs the same function as render_to_response feels really, really strange. It's convenient, but it just doesn't feel right and I'm not sure I can justify it. Interesting option though. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 22, 11:09 pm, Jan Oberst <[EMAIL PROTECTED]> wrote: > I'd protect all my forms if there's a neat way to do it. Why would it > only apply to logged-in users? I'm not using contrib.auth. It doesn't need to only apply to contrib.auth logged in users, but it should only be used for forms which are behind some kind of cookie- based protection (auth is the most obvious example, but if you've rolled your own authentication scheme you should be able to use SafeForm as well). There's no point in protecting a form which anyone can use (e.g. a public "contact us" form) as the purpose of CSRF is for an attacker to force you to perform an authenticated action that you don't want to perform - deleting something from a CMS for example. If anyone can use the form in question the attacker can just go and submit it themselves. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 22, 10:21 pm, "Jacob Kaplan-Moss" <[EMAIL PROTECTED]> wrote: > This makes me think -- is it possible that CSRF protection at the form > level is too low? Perhaps it's something that needs to be happening > at, say, the view level? Some sort of decorator, and/or a tag to spit > out the CSRF token in the template... Interesting thought. It feels like the form is the right place for this for a couple of reasons: 1. It involves adding an extra form field 2. When a CSRF check fails, it's polite to show a message. Form validation is a good place for this. The downside of doing it at the form level is the need to have access to the request and (potentially) the response as well, for setting a cookie. Doing things at the view level (with a decorator) provides access to both request and response objects, but doesn't provide access to form fields or validation errors. Maybe the answer is a combination of both - a form subclass and a decorator on the view? Will have to think about that. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Proposal: django.forms.SafeForm - forms with built in CSRF protection
On Sep 22, 10:01 pm, Brian Beck <[EMAIL PROTECTED]> wrote: > > > -- What about third-party app forms that aren't SafeForms, but need to > > > be? The situation dictates this, not the form author. > > I think we keep CSRF middleware around to deal with that. We also very > > actively encourage third party apps to adopt SafeForm as soon as 1.1 > > is out. > > But still, the situation dictates the need for SafeForm, not the form > author. If this becomes best practice, essentially *every* form will > need to be initialized with a request. One thing that might help out in this case would be the ability to create a SafeForm from a regular Form (which might be an argument for csrf protection as a feature of django.forms.Form rather than a subclass). If the third party code is well written (it follows the class-based generic view idiom for example, providing a get_form() method that can be over-ridden) it should be straight forward to intercept the form it creates and upgrade it to a SafeForm. You've reminded me of another problem with SafeForm: how does it interact with ModelForms? Is there a SafeModelForm as well? What about FormSets? Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Proposal: django.forms.SafeForm - forms with built in CSRF protection
CSRF[1] is one of the most common web application vulnerabilities, but continues to have very poor awareness in the developer community. Django ships with CSRF protection in the form of middleware, but it's off by default. I'm willing to bet most people don't turn it on. I don't believe middleware is the right way to approach this. It's too "magic" - it involves code that parses and re-writes your HTML as the response is being returned. It also means CSRF failures can't be gracefully handled - the middleware can throw up a big ugly error page, but ideally a CSRF failure would be treated the same way as a regular form validation error. I propose django.forms should include a SafeForm class, which is a subclass of Form that includes built-in protection against CSRF. I imagine the interface looking something like this: from django import forms class AddArticleForm(forms.SafeForm): headline = forms.CharField() author_email = forms.EmailField() # etc The interface to the form needs to be slightly different as the form needs access to the full request object - CSRF validation requires inspecting a cookie or session variable. Rather than passing request.POST I suggest passing just request: def add_article(request): if request.method == 'POST': # If the form has been submitted... form = AddArticleForm(request) if form.is_valid(): # All validation rules pass # Process the data in form.cleaned_data # ... return HttpResponseRedirect('/done/') else: form = AddArticleForm() response = render_to_response('add_article.html', { 'form': form, }) form.protect(response) return response Note the "form.protect(response)" at the end - it's a bit ugly, but we need some way of setting a cookie on the response that can later be used to verify that the form submission did indeed come from our own code. The template will need to include the hidden CSRF token fields: {{ form.non_field_errors }} {% for field in form %} {{ field.errors }} {{ field.label_tag }}: {{ field }} {% endfor %} {{ form.csrf_fields }} A CSRF failure message (I still haven't worked out the ideal user- facing copy for this, "Your form session has expired; please re- submit" is my current favourite) will be included as one of the non_field_errors. I'm also not sure how to deal with generating valid HTML in the above - {{ form.csrf_fields }} needs to be wrapped in a block level element for irritating reasons. I suggest using cookies for the additional token rather than sessions as doing so removes the dependency on Django's session framework (a good idea for large sites that don't want the overhead of storing thousands of inactive sessions). Why not build this in to django.forms.Form directly? Because CSRF is only an issue for forms that are supposed to only be used by authenticated users. Forms that don't require a cookie don't need to be protected. The other option would be for the django.forms.Form constructor to take a "csrf_protection=True" keyword argument, but this doesn't feel as neat as a subclass. That's as far as my thinking has got at the moment. I don't see any reason this needs to be developed from the start as a patch or branch against Django - it can be done as an external project and merged in to django.forms once the code is well tested and the API is finalized. (I'm totally up for working on this, but I really, really need to ship the new version of django_openid first.) Cheers, Simon [1] Some CSRF links for the uninitiated: * http://en.wikipedia.org/wiki/Cross-site_request_forgery * http://simonwillison.net/2008/talks/amajax-security/ * http://shiflett.org/articles/cross-site-request-forgeries --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---
Re: Template inheritance and {% include %} tags
On Sep 18, 11:58 pm, SmileyChris <[EMAIL PROTECTED]> wrote: > I think you missed the point, Simon. > > Michael isn't talking about self-referencing extending, he's talking > about blocks in statically included templates ({% include "bit.htm" > %}). Ah yes, sorry - misunderstood the original e-mail. Cheers, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~--~~~~--~~--~--~---