Re: Controlling form/widgets output
The FormRenderer idea is a good one. But how about generalised Renderer objects that take or inherit a template list, build a context and then can be passed around to fill in the details. Update-able at construction, processing or rendering, and able to be passed straight into another context for rendering? Like: from django.template import loader, Context def update_context(context, *dicts, **kwargs): for dict in dicts: context.update(dict) if kwargs: context.update(kwargs) return context class Renderer(object): "builds and renders a context" def __init__(self, templates = None, *dicts, **kwargs): "takes a list of templates, and any extra context" self.context = dict() self.update(*dicts, **kwargs).template = loader.select_template (templates or self.templates) def update_context(self, *dicts, **kwargs): "update the context that will be rendered" update(self.context, *dicts, **kwargs) return self def render(self, *dicts, **kwargs): "renders with any extra context, without updating, enabling flyweight, e.g. reuse by a widget in a form or a search result list." return self.template.render(update_context(Context (self.context), *dicts, **kwargs)) def __unicode__(self): "calls render so we can pass the renderer directly into another context, as if a string" return self.render() Didn't test it. ;) --~--~-~--~~~---~--~~ 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: Controlling form/widgets output
On Jan 21, 7:20 pm, Malcolm Tredinnick wrote: > In the larger scheme, I think this is one of those areas where people's > initial intuition differs. Django's form classes generally push > downwards, with the greater intelligence lying at the higher levels > (forms know the most, then form field classes have more localised > knowledge and the widgets have the least knowledge and are simply given > the information that they should present). Well, I can see that; it just seems to me that a form (and fields) should be responsible for managing data on the server side, while a widget is responsible for managing data on the client side. It has to be, since the Fields aren't running there. > Again, specific issues would be easier to address here, rather than > general complaints. We have a lot of accumulated experience to suggest > the current design isn't a total disaster and I'm yet to find anything > that isn't possible in a fairly neat fashion with the current dependency > direction. So what sort of things are you trying to do where you can't > think of a way to implement them at the moment? I'm trying to replace some of form elements on my site with Dojo widgets. In some cases I can handle it by just modifying attributes. But my foray into all this began because I needed to have the widgets being rendered in a form aware of some properties set on the form itself--so I could say something like "if you're rendering an INPUT element, add a 'class=form-input' attribute to the rendered html". I initially assumed I could just subclass Form, and add my custom Widget parameter to each Field. Then my Form could check when rendering a Widget whether it was a custom widget or not, and call a special rendering method if it was. But the Form rendering logic doesn't make that easy at all. I ended first iterating over all the fields in the form and calling a method which tells it what to do when it gets rendered, every time it gets rendered. Then I call the normal rendering functions, which work as expected. But I'm not very happy with that, since it relies quite a lot on some of the internal details of how Forms work. -- Chris --~--~-~--~~~---~--~~ 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: Controlling form/widgets output
On Thu, Jan 22, 2009 at 4:57 PM, catsclaw wrote: > Well, it seems to me that makes for an *extremely* tight coupling > between the model and the view. I'm sorry to be so blunt, but your perception is misguided. Forms have no dependancy upon models, nor do models on forms, nor must views use forms, models, or anything, really. *Model*Forms do of course have dependancies on both, but you can use a form without using models at all. I have Django apps in the wild that have no database connection, and I use forms just fine. I really think you need to do more research here. Maybe if you share exactly what you're trying to do we can help figure out why it seems so hard. > And it's a little difficult for me to > understand what value there is in such a tight coupling--if I've got a > DateField, why can't I have it represented in an HTML page by a > javascript calendar pop-up, or a text box, or three select boxes > (month, day, and year). It's difficult to understand because you've assumed it's impossible; it's not. A quick google search for "django datefield select" turns up http://www.djangosnippets.org/snippets/399/ as the first result; there's a few other recipes showing similar widgets. Using custom widgets is in fact incredibly easy. Start by reading http://docs.djangoproject.com/en/dev/ref/forms/widgets/#specifying-widgets, and follow on from there. > Plus, any time you collect a password you need to display it in a > form using a password input, not the stock text input. Again, this is in fact not only possible, but easy:: class MyForm(forms.Form): password = forms.CharField(widget=forms.PasswordInput) > And I might > very well have two separate form fields which should be displayed as a > single unit. This one's our fault: ``forms.ComboForm`` is what you want here, but it's not yet documented. Sorry! > There's a need to have the display decoupled from the > form logic. Django just doesn't provide much help in doing that. It's pretty decoupled. If you want a custom widget, write a custom ``Widget``. > In other words, if I create a > widget which renders a CharField and I'd like to validate the maximum > length, I either *must* inherit from TextInput or PasswordInput, edit > the CharField class, or write a different CharField class that's aware > of my new widget. No, you don't:: class MyForm(forms.Form): password = forms.CharField(widget=forms.PasswordInput, max_length=30) > If I were writing it, I'd make the Form class responsible for > defining the order of the fields, the labels, the validation logic and > errors. The Fields would be part of that. You just described exactly how Django's form package works. Seriously. The ``Form`` defines the order of fields (they're sorted in definition order), the validation logic (in the form of ``clean_*`` methods), and errors (as ``Form.errors``). - Why don't we start over here: what is the problem? What did you try do do? What did you expect to happen? What actually happened? 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: Controlling form/widgets output
On Jan 21, 5:37 pm, Russell Keith-Magee wrote: > > Here's just one example: when fields are written out to HTML, they > > get asked "what attributes does this kind of widget need?". > > Unless I'm misunderstanding your intent with this statement - No, they > aren't. A form contains fields, which describe the type of data that > is being collected and the validation procedures for said data. Each > field provides a widget, which describes a HTML element that allows > that data to be collected. When the form is rendered, it binds some > data to a field instance in a BoundField, and renders the BoundField > using the widget for the field. Well, it seems to me that makes for an *extremely* tight coupling between the model and the view. And it's a little difficult for me to understand what value there is in such a tight coupling--if I've got a DateField, why can't I have it represented in an HTML page by a javascript calendar pop-up, or a text box, or three select boxes (month, day, and year). Plus, any time you collect a password you need to display it in a form using a password input, not the stock text input. And I might very well have two separate form fields which should be displayed as a single unit. There's a need to have the display decoupled from the form logic. Django just doesn't provide much help in doing that. > The field isn't asked anything > during the rendering process beyond "what is your widget?". Not true. There's a "widget_attrs" method on the base Field class which passes a widget and expects to be passed back a dictionary of attributes to be added to the widget. In other words, if I create a widget which renders a CharField and I'd like to validate the maximum length, I either *must* inherit from TextInput or PasswordInput, edit the CharField class, or write a different CharField class that's aware of my new widget. > > Is there any work being done to clean up the way Django creates > > forms? I saw there was something being done with DOCTYPE > > declarations, but it didn't look like that was making very extensive > > changes. > > In short, no. We completed a major refactor of the forms framework > just before v1.0 landed, and we're not really looking to make another > major change. > > However - our commitment is to backwards compatibility, not to no > change at all. If you have a specific problem that can't be solved, > feel free to make a specific suggestion on how to improve things. If I were writing it, I'd make the Form class responsible for defining the order of the fields, the labels, the validation logic and errors. The Fields would be part of that. I'd make a FormRenderer class which was responsible for drawing a form in different formats (as a list, as a table, etc ...) and Widgets would act as a bridge between a Field (or group of fields) and the FormRenderer. -- Chris --~--~-~--~~~---~--~~ 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: Controlling form/widgets output
On Thu, 2009-01-22 at 08:37 +0900, Russell Keith-Magee wrote: > On Thu, Jan 22, 2009 at 7:39 AM, catsclaw wrote: [...] > > Adding a > > widget therefore requires rewriting the field classes you want the > > widget to be used with, rather than letting the widget interrogate the > > field classes. That's not great design, and it means any changes to > > form rendering becomes a major pain. > > Again - examples abound in the Django source tree that demonstrate > that this simply isn't true. In the larger scheme, I think this is one of those areas where people's initial intuition differs. Django's form classes generally push downwards, with the greater intelligence lying at the higher levels (forms know the most, then form field classes have more localised knowledge and the widgets have the least knowledge and are simply given the information that they should present). There's a little leakage, in the sense that field classes can pass down attributes, but its' not required. Also, the attributes that are passed down are a pretty common set (and, by and large, arbitrary, as they're just a dictionary, so you can pass in whatever you like via the form or fields). If there's a concrete example of what you can't get, that would be good to outline. I suspect that that is why some people might prefer the opposite direction for the dependencies, with widgets able to query fields. However that would lead to a different and, likely, greater set of problems with, for example, the over-arching form subclasses not able to get a hold of the bigger picture of what they're managing. To solve that and allow the reverse-dependencies, you end up having mutual dependencies, which bring their own set of problems to the table, in the design sense. Again, specific issues would be easier to address here, rather than general complaints. We have a lot of accumulated experience to suggest the current design isn't a total disaster and I'm yet to find anything that isn't possible in a fairly neat fashion with the current dependency direction. So what sort of things are you trying to do where you can't think of a way to implement them at the moment? Regards, Malcolm --~--~-~--~~~---~--~~ 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: Controlling form/widgets output
On Thu, Jan 22, 2009 at 7:39 AM, catsclaw wrote: > > Hi all -- > > I've started to poke around in customizing the generated form code > and providing my own widget instances, but the current Django form > code is written in such a way that it makes things nearly impossible. First off - as a general guide, hyperbolae will get you nowhere. I can point to several places in the Django codebase where custom widgets are used to override the default widget, so "nearly impossible" isn't a fair comment. > Here's just one example: when fields are written out to HTML, they > get asked "what attributes does this kind of widget need?". Unless I'm misunderstanding your intent with this statement - No, they aren't. A form contains fields, which describe the type of data that is being collected and the validation procedures for said data. Each field provides a widget, which describes a HTML element that allows that data to be collected. When the form is rendered, it binds some data to a field instance in a BoundField, and renders the BoundField using the widget for the field. Yes - there are entry points where HTML attributes can be injected into this rendering process, and there are some entry points where the field can push attributes into the widget, but otherwise it is the widget that is rendered, not the field. The field isn't asked anything during the rendering process beyond "what is your widget?". > Adding a > widget therefore requires rewriting the field classes you want the > widget to be used with, rather than letting the widget interrogate the > field classes. That's not great design, and it means any changes to > form rendering becomes a major pain. Again - examples abound in the Django source tree that demonstrate that this simply isn't true. > Is there any work being done to clean up the way Django creates > forms? I saw there was something being done with DOCTYPE > declarations, but it didn't look like that was making very extensive > changes. In short, no. We completed a major refactor of the forms framework just before v1.0 landed, and we're not really looking to make another major change. However - our commitment is to backwards compatibility, not to no change at all. If you have a specific problem that can't be solved, feel free to make a specific suggestion on how to improve things. 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 -~--~~~~--~~--~--~---
Controlling form/widgets output
Hi all -- I've started to poke around in customizing the generated form code and providing my own widget instances, but the current Django form code is written in such a way that it makes things nearly impossible. Here's just one example: when fields are written out to HTML, they get asked "what attributes does this kind of widget need?". Adding a widget therefore requires rewriting the field classes you want the widget to be used with, rather than letting the widget interrogate the field classes. That's not great design, and it means any changes to form rendering becomes a major pain. Is there any work being done to clean up the way Django creates forms? I saw there was something being done with DOCTYPE declarations, but it didn't look like that was making very extensive changes. -- Chris --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
ManyToManyField in both models/forms
Hi list, I had to implement M2M editing in both admin forms (something like editing userlist for group and grouplist for user). I wasn't able to find any fine solution, but specifying M2M in both models and creating tables manually (since syncdb tries to create two tables). I herd in the IRC, that such thing (editing in both forms) is abnormal, but I disagree. So I tried to use intermidiary model like described in the docs, but it is really another thing (not "pure" m2m). Another solution is hardcording the form, but it will require extra save code, I don't like it too. I think that if you add special arg (create_table) to ManyToManyField it can be easily implemented using models/fields/related.py:751. If you think it can go, I will create a ticket. Also there is (a kind of offtop) a very cute thing: http://www.djangosnippets.org/snippets/962/ Why isn't it in the native ManyToManyField? --~--~-~--~~~---~--~~ 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: Token parsing
On Thu, Jan 22, 2009 at 3:58 AM, Peter2108 wrote: > Not quite sure if this is the place to post this. Anyway, in the > module template.loader.tags the do_extends function parses a tokens > content like this:bits = token.contents.split() which does not > work correctly if the > extends path has a folder name with a space in it (as one of mine > did). I read in the docs on adding tags (http://docs.djangoproject.com/ > en/dev/howto/custom-template-tags/) that token.split_contents() should > be used so this looks like a bug. Yup, it is -- please file a bug in the ticket tracker. Thanks! 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 -~--~~~~--~~--~--~---
Token parsing
Not quite sure if this is the place to post this. Anyway, in the module template.loader.tags the do_extends function parses a tokens content like this:bits = token.contents.split() which does not work correctly if the extends path has a folder name with a space in it (as one of mine did). I read in the docs on adding tags (http://docs.djangoproject.com/ en/dev/howto/custom-template-tags/) that token.split_contents() should be used so this looks like a bug. Thanks, Peter --~--~-~--~~~---~--~~ 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: Joins and aggregates
On Wed, Jan 21, 2009 at 9:01 AM, Ludvig Ericson wrote: > > On Jan 21, 2009, at 14:10, Russell Keith-Magee wrote: > > Any opinions? Any other options that I may have missed? > > Sorry if I'm stating the obvious, but would it be > impossible to error out if two aggregates cause this > unexpected behavior? > > I mean then I'd say raising an exception for such queries > would be acceptable. Something like "unsatisfiable query". > > - Ludvig > > > > Is there a way to programatically determine if an aggregate is causing such a problem(without generating false positive) and therefore we could only do the subqueries where necessary. I don't think it's fair to the users of properly working aggregates, of which there are an awful lot, to impose either unneeded restrictions or overhead. Alex -- "I disapprove of what you say, but I will defend to the death your right to say it." --Voltaire "The people's good is the highest law."--Cicero --~--~-~--~~~---~--~~ 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: Joins and aggregates
>> 1) Prevent joins at the query level. Keep track of the joins >> that are being used for aggregates, and only allow one join. >> This would mean killing a lot of queries that work correctly >> right now, but would prevent the class of invalid queries. >> >> 2) Push aggregates into subqueries. Rather than try to >> accomodate aggregates using GROUP BY in the main query, >> generate a subquery for each aggregate and join the main >> query table onto the aggregate subquery table to provide the >> annotation. Obviously, this is going to get very expensive >> at the query level. >> >> Any opinions? Any other options that I may have missed? Is there a mid-way point? It looks like aggregates work with _one_ join, but not _more_ than one join. So possibly use aggregates as they currently stand for the _first_ one, and then use #2 above (aggregates in subqueries) for subsequently joined data. It allows you to maintain the efficient grouping queries for the common (single-table) joins, and only invokes the expense of #2 if there's a 2nd table for aggregation. I haven't waded into the QSRF+Aggregate code lately, so I don't know how easy it would be to add in "this is how many tables we've joined so far" tracking. -tim --~--~-~--~~~---~--~~ 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: Joins and aggregates
On Jan 21, 2009, at 14:10, Russell Keith-Magee wrote: > Any opinions? Any other options that I may have missed? Sorry if I'm stating the obvious, but would it be impossible to error out if two aggregates cause this unexpected behavior? I mean then I'd say raising an exception for such queries would be acceptable. Something like "unsatisfiable query". - Ludvig --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Joins and aggregates
Hi all, I've been looking at ticket #10060, The problem is caused by join behavior in aggregates, but I'm uncertain about the best way to address the problem. Using the example from the ticket, the problem goes like this: You can use double underscore notation for form joins in aggregates: >>> Branch.objects.annotate(total=Sum('center__client__loan__amount')) This will join tables as expected, and return objects annotated with a correct total. However, if a second deep-joined aggregate is added to the same query: >>> Branch.objects.annotate( total=Sum('center__client__loan__amount'), repaid=Sum('center__client__loan__payment_schedule__payments__principal')) the annotated `total` is much larger than it should be, by a factor determined by the cardinality of payment_schedules in each loan. Obviously, this is less than ideal. Unfortunately, the solution isn't trivial. The incorrect value for total is caused by the fact that total and repaid share the same chain of joins. However, if you split it out so that repaid uses a unique join chain, you still get an incorrect result - with a much larger multiplication factor (determined by the cardinality of center, rather than payment_schedules). Fundamentally, the issue here is abstraction leakage - SQL aggregates are more about the grouping procss than they are about the aggregate itself; the aggregate()/annotate() puts the emphasis on the aggregates, and implies the grouping. Now, the existing syntax works fine, as long as you are aware of the potential limitations. Unfortunately requires a little knowledge of the underlying SQL. This has always been true of Django's query language to an extent - my question to the group is how much do we want to lean on this limitation? If we decide to accept the limitations, obviously there is a big block of documentation required. I can see two alternatives to documentation: 1) Prevent joins at the query level. Keep track of the joins that are being used for aggregates, and only allow one join. This would mean killing a lot of queries that work correctly right now, but would prevent the class of invalid queries. 2) Push aggregates into subqueries. Rather than try to accomodate aggregates using GROUP BY in the main query, generate a subquery for each aggregate and join the main query table onto the aggregate subquery table to provide the annotation. Obviously, this is going to get very expensive at the query level. Any opinions? Any other options that I may have missed? 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 -~--~~~~--~~--~--~---