Re: Consistent exception handling in templates.
On Jul 9, 12:24 pm, Karen Tracey wrote: > I'm strongly against that idea. Swallowing errors makes it incredibly > difficult to debug errors. I would prefer for the `TEMPLATE_DEBUG` setting to > turn off much of the error-silencing currently done in template processing. > Yes, that means different behavior during development compared to > production. But running with DEBUG (template or otherwise) on IS different > from production, that's a given. And it this case it would allow for more > effective development since errors wouldn't be hidden away in nearly > impossible-to-find places. In my mind that's a tradeoff well worth making. > > See ticket #13167 for one example of where "template errors" have not been > silenced since before 1.0. If that case is to be be "fixed" now, I would > very much want that silencing to ONLY happen when TEMPLATE_DEBUG is False. > In my opinion silencing these during development would be a huge step > backwards. I think we are in agreement here. Swallowing errors makes it incredible difficult to debug errors. I would like to see the circumstances when exceptions are swallowed be more clearly defined, and ensure that only exceptions that are expected to be swallowed, are swallowed. If we can do that, then there should be no need for the behaviour to change based on the `TEMPLATE_DEBUG` setting. The problem with the inconsistent behaviour associated with this setting is exceptions that are expected to be swallowed, that we want to be swallowed, are not being swallowed in some cases when `TEMPLATE_DEBUG = True`. This can make it impossible to access some URLs on a website where such a condition is present, even though there is no actual error and the exception is expected to be silenced. It also results in some exceptions being transformed into `TemplateSyntaxError` sometimes, and the true exception raised other times. See ticket #16147 for an example where `TemplateDoesNotExist` is raised when the template DOES exist, because a template tag inside the template being loaded raises `TemplateDoesNotExist` at compile time, only when `TEMPLATE_DEBUG = True`. This can make it impractical to develop locally with `TEMPLATE_DEBUG = True`, because it can prevent access to working pages, which means you miss out on all the enhanced debugging that `TEMPLATE_DEBUG = True` provides when you encounter an actual error that needs developer attention. With the intent being that template authors should not be able to trigger HTTP 500 errors on a production site, couldn't we achieve that by silencing exceptions raised when an invalid argument was passed to a template tag (e.g. `ValueError` or `TypeError` in the template tag code), but allowing exceptions raised in the code for the object that was passed in to the template tag as an argument? For example, if an object that calculates and returns a number when evaluated is passed to `{% widthratio %}`, but there is a bug in the code of that object and it raises some kind of exception when evaluated, that should not be silenced. It should bubble up so that the developer is alerted to a problem in the code for that object (not an error that the template author has made by passing an invalid argument). However, if there was no exception raised in evaluating the object, but it simply returned something other than a number, then that should behave the same as if an empty string or missing template variable was passed in and no exception should be raised. I think that a `TemplateSyntaxError` should be raised at compile time if an invalid template tag is used (unknown, too few or too many arguments). The `render()` function for a template tag should silence exceptions raised when arguments with the incorrect type or value are provided, but should not silence exceptions raised when evaluating the arguments themselves (or properties on the arguments). Cheers. Tai. -- 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: Consistent exception handling in templates.
On Fri, Jul 8, 2011 at 9:55 PM, Tai Lee wrote: > Secondly, there is the inconsistent behaviour between production and > development environments related to the `TEMPLATE_DEBUG` setting. I > think that if an exception is intentionally silenced in production, it > should also be intentionally silenced with `TEMPLATE_DEBUG = True`, to > allow for consistent behaviour during development. > I'm strongly against that idea. Swallowing errors makes it incredibly difficult to debug errors. I would prefer for the TEMPLATE_DEBUG setting to turn off much of the error-silencing currently done in template processing. Yes, that means different behavior during development compared to production. But running with DEBUG (template or otherwise) on IS different from production, that's a given. And it this case it would allow for more effective development since errors wouldn't be hidden away in nearly impossible-to-find places. In my mind that's a tradeoff well worth making. See ticket #13167 for one example of where "template errors" have not been silenced since before 1.0. If that case is to be be "fixed" now, I would very much want that silencing to ONLY happen when TEMPLATE_DEBUG is False. In my opinion silencing these during development would be a huge step backwards. Karen -- 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: Consistent exception handling in templates.
On Jul 8, 11:31 pm, Jacob Kaplan-Moss wrote: > > [...] but some of Django's own template tags (e.g. `widthratio`) don't > > adhere to > > this policy. > > These are bugs, and should be fixed. Thanks for this clarification. I will try to review the built-in tags and submit some patches to fix these bugs. For added clarity, should a template tag behave the same when a string or variable is passed as it's argument? E.g. if the first argument to a template tag is expected to be a number, we can validate that and raise a `TemplateSyntaxError` at compile time if it is passed in as a literal, but we can only validate it and fail silently at render time if it is passed in as a template variable. I believe that this behaviour is inconsistent and confusing, and can lead to unexpected and difficult to trace problems. To avoid this, should the validation of arguments to template tags that can be passed in as either literals or template variables be limited to checking that an argument was passed, and delay type or value checking until render time, which will always fail silently? > I'm against this, for a whole host of reasons — the crux of which > comes down to the philosophy that templates are *not* a programming > language, and introducing a try/except concept into them is about > seven steps too far. > > The point of the template language is to give front end designers and > developers the space to explore without the persnicketiness a > so-called "real" programming language introduces. What you're asking > for here is to fundamentally change the philosophy of the template > language. If you disagree that fundamentally with the ideas behind the > template language I really think you'll be better off finding another > one than trying to swim upstream. I agree that what I suggested would be a fundamental change, and not likely to be adopted in full. However, I would still like to hear other ideas from the community about smaller steps that we could take that would make exception handling more consistent and selective, without changing the fundamental philosophy of the template language. Firstly, Jonathan Slenders makes the point that perhaps not ALL exceptions should be silenced. Secondly, there is the inconsistent behaviour between production and development environments related to the `TEMPLATE_DEBUG` setting. I think that if an exception is intentionally silenced in production, it should also be intentionally silenced with `TEMPLATE_DEBUG = True`, to allow for consistent behaviour during development. If an exception IS worth raising when `TEMPLATE_DEBUG = True`, it should also raise in production, and these types of exceptions should be caused by an underlying problem in the template tag or the evaluation of an object passed to the template tag, rather than something that a template author is likely to trigger because they are not programmers. Does anybody else have ideas or suggestions about these two issues, or other small improvements we could make to exception handling in templates without fundamentally changing the philosophy of the template language? Cheers. Tai -- 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: Form Rendering API Proposal
Hi Chris, On 07/08/2011 04:00 PM, Chris Beaven wrote: > On Saturday, July 9, 2011 12:19:44 AM UTC+12, Gregor Müllegger wrote: > [...] So we decided to skip changing a widget totally in the form > rendering. > Displaying a form and anything else that happens in the template has a > representational purpose, so we saw it would be out of scope for the > project. > However changing the template that is used to render a widget will > of course > still be possible (also passing in extra arguments etc.) > > > Fair enough, I understand the concern with giving HTML power over choice > of rendered widget (not sure I totally agree, but concede that it's > easier to not have to worry about it). We can always revisit additional features later if needed, but scope creep is a GSoC-killer. I think most of the use cases for replacing widgets in the template are really purely representational, they don't change the server-side data handling at all. In cases where it would, the existing proposal was already inadequate. And the majority of cases, when it wouldn't, can be handled just by swapping in a different template; there's no need to care about the widget class. If the form officially is using a TextInput widget on the Python side and you swap in a template for that field that renders a select dropdown, the Python code won't care; it still gets a name and a value in request.POST. > I guess this means that rendering a field as "hidden" in the template is > also out, since this needs to modify more than just the field's > representation (specifically, non_field_errors). Yes. I mean, you're fully free to render a field as hidden yourself (via template), but anytime you make a change in the HTML that implies any change in server-side data handling, you're on your own to figure out the right solution for your case (which is no different than now). > Now that we drop the idea of exchanging widgets we also don't longer > need the > widgets template variable that holds the possible widget > implementations you > can drop in. But the formfields var would be left to decide cases like: > > {% formconfig widget using "textarea.html" for formfields.CharField %} > > [or] > > {% formconfig widget using "textarea.html" for "CharField" %} > > I'm not sure I see the importance of overriding a widget's template, to > be honest. IMO it seems much more likely that you'll be worried with > alternate rendering for different fields rather than all widgets. Seems like there might be a small misunderstanding here. The shown syntax is for overriding the widget template used for any instances of a given _field_ type, not a given _widget_ type. I agree that a more common use case is probably changing things up for a particular field in your form, but having this allows the possibility of reusable form layouts that can do interesting things with representations of particular field types. > btw I also plan to use "field" as argument for formconfig instead of > "widget" > to match more the {% form[row|field] %} tags: > > {% formconfig field using "textarea.html" with placeholder="type here > …" for "CharField" %} > > I worry that we're introducing two meanings of what 'for' represents. > Again, it seems to make more sense in my mind that it'd be in context of > a field, not a widget. I think it's actually pretty intuitive in practice that the operand of "for" can be either the name of a specific field, or the name of a field class. Ambiguity isn't an issue; specific field names take precedence (and capitalization conventions should prevent ambiguity anyway). And like I said above, I think the latter is useful for reusable form layouts. > Now to your django-forms implementation that has the "extends" > argument for > the {% form %} tag. I still totally like the idea behind that, but > like I > already said in the other message -- it might be confusing to have two > different meanings of the block tag. Carl has the same opinion here > so we > won't include that into our implementation. > > (Note that 'extends' also applies the formconfig, row and field tags too) > > I understand the potential for confusion, but I think it really does > bring something big to the table which is unfortunate to miss out on. > For example, if I just want to customize one field template on a form > then without this I have to redefine the whole form template. > It also allows for complex redefinition of a field's label and help text > without having to redefine the entire field template. Why would you otherwise have to redefine the whole form template? A form template is a normal template; you can put blocks in it and have another form template extend it and override those blocks. I don't think it's onerous (in fact, I think it's clearer and more maintainable) to do this in a separate file rather than "inline" as your proposal does. And I'
Re: Form Rendering API Proposal
On Saturday, July 9, 2011 12:19:44 AM UTC+12, Gregor Müllegger wrote: > > [...] So we decided to skip changing a widget totally in the form > rendering. > Displaying a form and anything else that happens in the template has a > representational purpose, so we saw it would be out of scope for the > project. > However changing the template that is used to render a widget will of > course > still be possible (also passing in extra arguments etc.) > Fair enough, I understand the concern with giving HTML power over choice of rendered widget (not sure I totally agree, but concede that it's easier to not have to worry about it). I guess this means that rendering a field as "hidden" in the template is also out, since this needs to modify more than just the field's representation (specifically, non_field_errors). > Now that we drop the idea of exchanging widgets we also don't longer need > the > widgets template variable that holds the possible widget implementations > you > can drop in. But the formfields var would be left to decide cases like: > > {% formconfig widget using "textarea.html" for formfields.CharField %} > [or] > {% formconfig widget using "textarea.html" for "CharField" %} > I'm not sure I see the importance of overriding a widget's template, to be honest. IMO it seems much more likely that you'll be worried with alternate rendering for different fields rather than all widgets. > We justified it because this concept of matching a string to python > structure > already exists. Examples are {% load mytemplatelib %} that loads a file > named > after the argument, or some app.Model arguments used in third party libs. > That's a bit of a far-reaching justification, but I'm indifferent about the whole widget template bit of the proposal, so roll with whatever makes most sense. > btw I also plan to use "field" as argument for formconfig instead of > "widget" > to match more the {% form[row|field] %} tags: > > {% formconfig field using "textarea.html" with placeholder="type here > …" for "CharField" %} > I worry that we're introducing two meanings of what 'for' represents. Again, it seems to make more sense in my mind that it'd be in context of a field, not a widget. > Now to your django-forms implementation that has the "extends" argument for > the {% form %} tag. I still totally like the idea behind that, but like I > already said in the other message -- it might be confusing to have two > different meanings of the block tag. Carl has the same opinion here so we > won't include that into our implementation. > (Note that 'extends' also applies the formconfig, row and field tags too) I understand the potential for confusion, but I think it really does bring something big to the table which is unfortunate to miss out on. For example, if I just want to customize one field template on a form then without this I have to redefine the whole form template. It also allows for complex redefinition of a field's label and help text without having to redefine the entire field template. We're already bringing a new concept of inline sub-template definition via the 'using' argument. I don't see that it's much more of a push to simultaneously introduce inline sub-template extension via the 'extends' argument. Here's real-life example off the top of my head we had the other day. A client had a multi-step registration form. Usually, our rows show a * next to the label of required fields but all of the first step was required so the client didn't want the stars to show. I envision this would look like this in django-forms (lets assume we've customised 'forms/field/base.html' to conditionally conditionally change the label class or just conditionally add the * after it): {% form form extends "forms/p.html" %} {% block config %} {% formconfig field with required=0 %} {% endblock %} {% endform %} What would this look like with the current form proposal? > -- You received this message because you are subscribed to the Google Groups "Django developers" group. To view this discussion on the web visit https://groups.google.com/d/msg/django-developers/-/rkqDXMP8x6AJ. 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: Consistent exception handling in templates.
On 07/08/2011 05:24 PM, Jonathan Slenders wrote: My feeling is that we should silence TypeError, AttributeError and KeyError in _resolve_lookup, but only when they occur one frame deep. I agree with what you propose but AFAIK it's not easy to solve without doing frame analysis (I'd say that feature is not worth doing such hacks). That's because of the way `hasattr` is implemented: def hasattr(obj, attr): try: getattr(obj, attr) return True except AttributeError: return False This code directly mirrors the code found in CPython and implies that /hasattr "executes" properties/. So there's no way to figure out whether an attribute exists without executing the code of properties. Jonas -- Django + MongoDB: http://django-mongodb.org -- 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: Consistent exception handling in templates.
Something related I was wondering about... Errors in templates should be silenced -- I agree with that -- but only when they are caused by an error in the template. Variable.resolve can fail silent because that's caused by the template author, who is referring to non-existing variables. However, sometimes, it happens to me that the template calls a @property of some object, which acesses at his turn an non existing attribute of another object. An AttributeError is raised, but because that's somewhere in Variable.resolve, it's silently ignored. It's clear that at that point, it's not something in the template, but a hard-to-find bug in the @property. My feeling is that we should silence TypeError, AttributeError and KeyError in _resolve_lookup, but only when they occur one frame deep. Maybe I am wrong here, it's also just an opinion, and I have no real solution... (Except for writing better unit-tests for the application logic.) -- 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: Consistent exception handling in templates.
On Thu, Jul 7, 2011 at 8:37 PM, Tai Lee wrote: > The docs say that when writing custom template tags, the `render()` > function should never raise `TemplateSyntaxError`, [...] This rule is the correct one, and I'm very much against changing it. > [...] but some of Django's own template tags (e.g. `widthratio`) don't adhere > to > this policy. These are bugs, and should be fixed. > I'd like to see a move towards consistent exception handling in > templates for template tags and filters. I'd like to see no exceptions > silenced by default, but provide a way for template authors to > conditionally silence exceptions in fragments of their templates. > Perhaps with a block tag. I'm against this, for a whole host of reasons — the crux of which comes down to the philosophy that templates are *not* a programming language, and introducing a try/except concept into them is about seven steps too far. The point of the template language is to give front end designers and developers the space to explore without the persnicketiness a so-called "real" programming language introduces. What you're asking for here is to fundamentally change the philosophy of the template language. If you disagree that fundamentally with the ideas behind the template language I really think you'll be better off finding another one than trying to swim upstream. > Should built-in template tags follow the advice given in the docs, and > never raise `TemplateSyntaxError` in their `render()` function? Yes; the two instances you mentioned are bugs and should be fixed. Jacob -- 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: Form Rendering API Proposal
Hi Chris, 2011/6/29 Chris Beaven : >> >> I think thats conceptually not possible. We simply can change the widget >> during >> template rendering time, which makes it impossible to decide in the python >> code with which widget we end up. And theoretically we could even render >> the >> form twice with different widgets. Or throw the rendered template away >> without >> using the widget at all. > > In this case, why do we even have this format: {% formconfig widget > widgets.Textarea for "comment" %} and the terminology of widgets? > It seems like that should really just boil down to {% formconfig field using > "some/textarea.html" for "comment" %} and just referring to fields only. A > widget to me encompasses the backend logic of decoding the data, etc. > I think it'd be a great plus if we *could* make it work for different > widgets. This would really give power to change forms dynamically at the > template layer. > I remember thinking a while ago about some kind of widget repository > available to the templates, combined with a hidden input per field that > could notify the python form of the alternate widget used (the hidden input > only used if the widget differed than the default for that field). This > would allow for the same form to be used with different templates which used > completely different widgets. So I spoke to Carl yesterday about some of the ideas you brought up and we agreed on how we want to handle them :-) You've mentioned if being able to change the widget in the template it would be cool to let the python source also know which widget should then be used to parse the data. My concern about this was that an HTML data value should not be allowed to exchange code parts on the server. Sure we would limit that to specific widget classes, but with that power in HTML you would be able to break the server side code, either by being evil or not understanding widgets in total. The same of course is true if we just change the widget without letting the python form know what is happening, this makes it also possible to break the server … we talked then about what a widget actually is: It has two purposes, first is parsing the data making it usable for the field, second is representational -- rendering an HTML input that is compatible with the widget's data format. So we decided to skip changing a widget totally in the form rendering. Displaying a form and anything else that happens in the template has a representational purpose, so we saw it would be out of scope for the project. However changing the template that is used to render a widget will of course still be possible (also passing in extra arguments etc.) Now that we drop the idea of exchanging widgets we also don't longer need the widgets template variable that holds the possible widget implementations you can drop in. But the formfields var would be left to decide cases like: {% formconfig widget using "textarea.html" for formfields.CharField %} We decided to drop that variable as well, replacing it with a string that can match the class name of a field: {% formconfig widget using "textarea.html" for "CharField" %} We justified it because this concept of matching a string to python structure already exists. Examples are {% load mytemplatelib %} that loads a file named after the argument, or some app.Model arguments used in third party libs. There might be the concern that "CharField" is ambiguous if some else also implements a "CharField". But this might be even a feature … if someone implements also a CharField it might be very similar to django's built-in one, otherwise you would name it differently. btw I also plan to use "field" as argument for formconfig instead of "widget" to match more the {% form[row|field] %} tags: {% formconfig field using "textarea.html" with placeholder="type here …" for "CharField" %} Now to your django-forms implementation that has the "extends" argument for the {% form %} tag. I still totally like the idea behind that, but like I already said in the other message -- it might be confusing to have two different meanings of the block tag. Carl has the same opinion here so we won't include that into our implementation. Thanks a lot again for your input, it created some vital think processes for me and resulted in good improvements on the proposal (hope you see it the same). Keep posting. -- Servus, Gregor Müllegger -- 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.