Re: Not calling things twice in templates

2013-06-03 Thread Russell Keith-Magee
On Mon, Jun 3, 2013 at 1:20 PM, Shai Berger  wrote:

> On Monday 03 June 2013, Russell Keith-Magee wrote:
> > Alternatively, add new sub tags to {% for %}:
> >
> > {% for bee in my_bonnet.bees %}
> > {% pre %}
> > 
> > {% body %}
> > {{ bee }}
> > {% post %}
> > 
> > {% empty %}
> > No bees in your bonnet.
> > {% endfor %}
> >
> > but that's starting to get verbose, and leaves ambiguous what to do with
> > content appearing between the opening {% for %} and the {% pre %}
> >
> It's also sort of available already:
>
> I'm fully aware that it's *possible*  to handle already. The point is that
it's such a common use case that is should be easy to render without
requiring an extra 4 lines of obscure template logic, an extra 2 levels of
indentation, or an expensive double calculation.

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Not calling things twice in templates

2013-06-03 Thread Daniele Procida
On Mon, Jun 3, 2013, Russell Keith-Magee  wrote:

>> But this is another common pattern:
>>
>> {% if my_bonnet.bees %}
>> 
>> {% for bee in my_bonnet.bees %}
>> {{ bee }}
>> ...
>>
>> The problem here is that my_bonnet.bees gets asked for twice, and it could
>> be my.bonnet(), some very expensive function.

>Any other syntax I can think of requires introducing another indentation
>level. Have you got a specific suggestion for how to address this?

Not really. I wasn't even sure if would be considered much of an issue.

But I can think of two:

* introducing a template syntax that means "don't re-fetch"
 
perhaps: !my_bonnet.bees or: my_bonnet.bees.cached

I don't know if the latter would even be possible.


* managing it at the function level

The template author might not even know which functions are expensive. So 
perhaps it should be the function writer's responsibility to make take care of 
this:

@expensive
def bees(self):

which will tell the template system not to re-evaluate it while serving the 
same request.


I think I like this second suggestion better, because it keeps templates as 
simple as possible. And this way, the template author won't have to worry about 
keeping up-to-date with re-written functions that have become more expensive or 
less expensive.

Daniele

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Why apps have to have unique names? [related with subapps and name collision]

2013-06-03 Thread Jorge C . Leitão
Hi. 

The motivation to this question is that if I want to implement "copies" of 
an app within an website (for instance, a stackoverflow-like where each app 
is a Q&A for its own, but with modifications on templates, urls, etc.), as 
far as I'm understanding: (1) each "copy" has to change its name, names of 
all calls of templates, views, etc due to name collision and (2) each copy 
must be an app on its own without any dependencies on other apps with 
models/templates/urls, because otherwise the dependent apps would also have 
to be "copied", names changed, etc.

In a previous post I suggested generalizing templates and url search to be 
used within subapps (apps with folder inside another app), which I found 
was a way of allowing what I wanted to do.
There was a criticism that during the discussion that I (mostly) ignored, 
but while re-reading it, I understood its meaning and its importance to a 
discussion by itself.

The criticism was from Shai Berger, that correctly pointed out that Django 
uses unique app names [1], and what I didn't understood at the time was 
that this forbids any possibility of using subapps the way I was suggesting 
or in any way that might help.

Motivated by that criticism, I want to ask: why apps have to have unique 
names?

To try to answer this question on the code, I did a simple search on Django 
code. This is far from rigorous, but gives some nice results. The search 
was simple: regex of r"settings.INSTALLED_APP" and regex of 
r".split('.')[-2]". Afterwards, I read the code to understand which 
dependencies it has on the labeling. Here are the results:

## Usage of settings.INSTALLED_APP (regex: settings.INSTALLED_APP)
# To check admin existence, uses full path (import_module)
/django/contrib/admin/__init__.py:24: for app in 
settings.INSTALLED_APPS:
# To check specific app existence, uses full path (import_module)
/django/contrib/admin/templatetags/admin_static.py:6: if 
'django.contrib.staticfiles' in settings.INSTALLED_APPS:
/django/contrib/comments/__init__.py:16: if comments_app not in 
settings.INSTALLED_APPS:
/django/contrib/gis/tests/__init__.py:113: settings.INSTALLED_APPS 
= list(self.old_installed) + new_installed
/django/contrib/gis/tests/__init__.py:125: settings.INSTALLED_APPS 
= self.old_installed
/django/contrib/messages/tests/base.py:16: 'django.contrib.auth' 
not in settings.INSTALLED_APPS,
/django/contrib/messages/tests/base.py:214: lambda 
app:app!='django.contrib.messages', settings.INSTALLED_APPS),
/django/contrib/messages/tests/base.py:239: lambda 
app:app!='django.contrib.messages', settings.INSTALLED_APPS),
/django/contrib/sitemaps/tests/flatpages.py:8: 
@skipUnless("django.contrib.flatpages" in settings.INSTALLED_APPS,
/django/contrib/sitemaps/tests/http.py:88: 
@skipUnless("django.contrib.sites" in settings.INSTALLED_APPS,
# for finding static; use full path of the app
/django/contrib/staticfiles/finders.py:122: apps = 
settings.INSTALLED_APPS
# for binding commands to the management. Requires unique app to avoid 
commands collision.
/django/core/management/__init__.py:101: apps = 
settings.INSTALLED_APPS
# for binding commands to the management. Requires unique app to avoid 
commands collision.
/django/core/management/__init__.py:319: options += 
[(a.split('.')[-1], 0) for a in settings.INSTALLED_APPS]
# for importing the 'management' module within each installed app, to 
register dispatcher events.
/django/core/management/commands/flush.py:35: for app_name in 
settings.INSTALLED_APPS:
# for importing the 'management' module within each installed app, to 
register dispatcher events (lacks DRY principle: command used is the same 
as previous file.)
/django/core/management/commands/syncdb.py:38: for app_name in 
settings.INSTALLED_APPS:
# for the 'models' of the db. It uses django.utils.importlib.import_module 
on the full app's path. Class uses _label_for for defining a "name" for the 
app, which requires unique app
/django/db/models/loading.py:61: for app_name in 
settings.INSTALLED_APPS:
/django/db/models/loading.py:143: for app_name in 
settings.INSTALLED_APPS:
# To check whether the model is installed. It uses full paths of the package
/django/db/models/options.py:71: self.installed = 
re.sub('\.models$', '', cls.__module__) in settings.INSTALLED_APPS
# To find templatetags. It stores the full path of the module
/django/template/base.py:1271: for app_module in ['django'] + 
list(settings.INSTALLED_APPS):
# To find templates. It stores the full path of the module
/django/template/loaders/app_directories.py:19: for app in 
settings.INSTALLED_APPS:
# To find templates. Depends on the pkg_resources.resource_string to tell 
wether it returns app name of full app name
/django/template/loaders/eggs.py:23: for app in 
settings.INSTALLED_APPS:
# To check specific app existe

Re: Composite fields once again

2013-06-03 Thread Anssi Kääriäinen


On 2 kesä, 23:20, Luke Sneeringer  wrote:
> On Jun 2, 2013, at 8:22 AM, Michal Petrucha  wrote:
>
> > GenericForeignKey and nontrivial field types
> > 
>
> > As I've indicated in my proposal, just casting any value to a string
> > and then performing a reversible transformation on such strings may
> > work well enough for string and integer database columns, not so much
> > for things like dates, timestamps IP addresses or other similar types.
>
> > Any ideas on how to make this work? Should I try to extend the backend
> > API to include explicit casts for each nontrivial column type to a
> > string representation equal to the one used by Python? Or should I
> > just document this as unsupported?
>
> There's already a `db_type` method that you can override (that receives a 
> `connection` object) for the actual database type. It's pretty easy to do 
> something to the effect of (for instance):
>
>     if 'postgres' in connection['ENGINE']:
>         return 'uuid'
>     if 'mysql' in connection['ENGINE']:
>         return 'char(36)'
>     [...]
>
> However, having done some work myself on trying to create non-trivial field 
> subclasses, it's everything after that which gets difficult. Django provides 
> an overridable method to cast the value, but nothing for anything else in the 
> expression (the field or the operator), which are hard-coded into the 
> backend. (This is a source of frustration for me personally, because it makes 
> it very difficult to write classes for, say, PostgreSQL arrays, without 
> either resorting to massively ugly syntax or subclassing nearly every single 
> class involved in the process of creating a query (Manager, QuerySet, Query, 
> WhereNode...)
>
> I ultimately went through the subclass-half-the-world technique quite 
> recently (a couple of weeks ago), as I want some non-trivial custom fields 
> for a new project I am about to start for my company (sadly, the project is 
> private, although I'd be happy to share field code if it would help in any 
> way). What I ended up doing is checking the Field subclass for a custom 
> `get_db_lookup_expression` method (that's not a Django field method -- I made 
> it up), and then my Field subclasses could use that to return a full 
> expression in the form "{field} = {value}". If the method is present and I 
> get something (other than None) back from that method, then use it, otherwise 
> I pass it on to the DatabaseOperators class for its usual processing. Using 
> that method prevents me from having to modify a monolithic DatabaseOperators 
> subclass for each new field I add (it seems to me that fields should know how 
> to perform their lookups).
>
> The other challenge was defining the QuerySet lookup expressions. Django 
> essentially hard-codes the things it understands for lookups (e.g. 
> Foo.objects.filter(bar__gt=5) being transformed into "select ... from app_foo 
> where bar > 5"). The set of lookup suffices (exact, gt, gte, lt, lte, etc.) 
> is, sadly, also essentially hard-coded. I wrote an ArrayField to use 
> PostgreSQL arrays, and really wanted a way to be able to lookup based on the 
> length of the array (so, something like `Foo.objects.exclude(photos__len=0)`, 
> for instance, to give me all Foos with no photos). I did manage to make that 
> work, but it was a struggle. Also, the set of lookup suffices is universal, 
> even though some of them don't make sense on some fields ("year" on 
> IntegerField, for instance).
>
> So, my ideas on getting non-trivial field subclasses to work is basically:
>
> 1. Make fields be the arbiter of what lookup types they understand. 
> (IntegerFields shouldn't understand "year"; maybe someone's ArrayField 
> subclass does understand "len".) This probably needs to be something that can 
> be determined on the fly, as composite fields will probably need lookup types 
> corresponding to their individual sub-fields.
>
> 2. Make lookup types chainable. In the Array "len" example, 
> `photos__len__gt=5` makes sense.
>
> 3. Make it so fields define how they are looked up based on database engine 
> and lookup type.
>
> Moving these things into the Field implementation (rather than in the 
> backend) should mean that non-trivial field subclasses become much easier. 
> It'll also eliminate the need for, say, django.contrib.gis to have an 
> entirely different set of backends -- a large reason gis jumps through those 
> hoops (as best as I can tell from reading it; disclaimer: I am not a 
> contributor) is to work around the restrictions being described.
>
> I hope that helps your thinking. I have this stuff fresh in my head because 
> I've just worked on an implementation for PostgreSQL arrays and composite 
> fields that I need for my work. While I've thought a decent bit about 
> extensibility (for my own purposes), I haven't open-sourced it largely 
> because I know I haven't solved all the problems yet. Having read your 
> e-mail, I now ho

Re: Why apps have to have unique names? [related with subapps and name collision]

2013-06-03 Thread Aymeric Augustin
2013/6/3 Jorge C. Leitão 

Motivated by that criticism, I want to ask: why apps have to have unique
> names?
>

Hi Jorge,

Django assumes that a model can be identified by (app_name,
model_name). Long ago — 8 years ago — it didn't seem to be a problem.

I'm not sure your research covers all the consequences of this assumption.
Anything that hits the app cache depends on this assumption:
- the target of foreign keys can be expressed as 'app_name.ModelName'
- the fixture format identifies models with app_name.ModelName
- several settings have a value in the form app_name.ModelName
- django.contrib.contenttypes uses (app_name, model_name) to identify each
model
- since permissions are tied to content types, this assumption bleeds to
django.contrib.auth
- etc.

Lifting the requirement of uniqueness would require switching anything that
uses the app_name.ModelName format to full.path.to.app.ModelName.
That would be quite disruptive, not only for Django, but for the entire
ecosystem of apps, starting with contrib apps. The real question is --
what's the story for authors of pluggable apps ? for users of the framework
?

As far as I know, the explanation for this behavior lies in history more
than in a design decision. Until now, no one judged this to be enough of a
problem to make a proposal to fix it. To be honest, it's frighteningly hard
to fix. Even app-loading (ticket #3591) doesn't tackle it.

-- 
Aymeric.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Why apps have to have unique names? [related with subapps and name collision]

2013-06-03 Thread Yishai Beeri
Is this not almost trivial to work around by creating a new module  
'newapp', importing the original app code from it, and then using  
'path.to.newapp' as a new "copy" of the app in INSTALLED_APPS?


Yishai

On Mon, 03 Jun 2013 12:24:38 +0300, Aymeric Augustin  
 wrote:



2013/6/3 Jorge C. Leitão 

Motivated by that criticism, I want to ask: why apps have to have unique

names?



Hi Jorge,

Django assumes that a model can be identified by (app_name,
model_name). Long ago — 8 years ago — it didn't seem to be a problem.

I'm not sure your research covers all the consequences of this  
assumption.

Anything that hits the app cache depends on this assumption:
- the target of foreign keys can be expressed as 'app_name.ModelName'
- the fixture format identifies models with app_name.ModelName
- several settings have a value in the form app_name.ModelName
- django.contrib.contenttypes uses (app_name, model_name) to identify  
each

model
- since permissions are tied to content types, this assumption bleeds to
django.contrib.auth
- etc.

Lifting the requirement of uniqueness would require switching anything  
that

uses the app_name.ModelName format to full.path.to.app.ModelName.
That would be quite disruptive, not only for Django, but for the entire
ecosystem of apps, starting with contrib apps. The real question is --
what's the story for authors of pluggable apps ? for users of the  
framework

?

As far as I know, the explanation for this behavior lies in history more
than in a design decision. Until now, no one judged this to be enough of  
a
problem to make a proposal to fix it. To be honest, it's frighteningly  
hard

to fix. Even app-loading (ticket #3591) doesn't tackle it.


--
You received this message because you are subscribed to the Google Groups "Django 
developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Not calling things twice in templates

2013-06-03 Thread Patryk Zawadzki
2013/6/3 Andre Terra :
> Well, Russ, you asked for suggestions, so here's a couple half-hearted
> attempts.
>
> Perhaps we could allow for if clauses in the with block or vice-versa? It
> could be argued that it would reduce readability and/or induce confusion
> with conditional expressions[0], and I would have to agree.
>
> {% with my_bonnet.bees as bees if my_bonnet.bees %}
> {# could be confused with conditional expressions #}
> 
> {% for bee in bees %}
> {{ bee }}
> {% endfor %}
> 
> {% else %}
> No bees!
> {% endwith %}

What about:

{% with nonempty my_bonnet.bees as bees %}

{% for bee in bees %}
{{ bee }}
{% endfor %}

{% endwith %}


-- 
Patryk Zawadzki
I solve problems.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Making __repr__ safe by default

2013-06-03 Thread Patryk Zawadzki
2013/5/19 Karen Tracey :
> I agree with Anssi, repr should stay as-is. I do a lot of shell/pdb work and

In interactive mode it's just as easy to call __unicode__ as it is to
call __repr__. On the other hand __repr__ is used by automated tools
such as crash reporters (raven).

> I can't recall ever encountering a problem with "unsafe" repr.

We had it explode a number of times when coupled with postgres. In
that case instead of the original exception, all you get is:

psycopg2.ProgrammingError: current transaction is aborted, commands
ignored until end of transaction block

> I think many
> people would find it annoying if suddenly repr would tell you no more than
> the pk of the object.

I'd argue that the PK is actually more important than whatever
__unicode__ returns. It's really annoying to find a stack trace that
only contains product's title when you have tens of millions of
products on production and title is not an indexed field. And by that
time it's already too late to override __repr__. On the other hand
it's fairly easy to extend __repr__ to display other information if
you find it more useful than the PK.

Backward compatibility should not be a concern here as no code should
depend on whatever __repr__ chooses to return.

-- 
Patryk Zawadzki
I solve problems.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Why apps have to have unique names? [related with subapps and name collision]

2013-06-03 Thread Michal Petrucha
On Mon, Jun 03, 2013 at 01:04:34PM +0300, Yishai Beeri wrote:
> Is this not almost trivial to work around by creating a new module
> 'newapp', importing the original app code from it, and then using
> 'path.to.newapp' as a new "copy" of the app in INSTALLED_APPS?

Not really. At least not for models. There is some magic, I'm not sure
if it's in AppCache or in the model metaclass, which inspects the
import path in which the model class is located and uses it to
identify the model class. That means, if you just import another
application's models, they will still be recoginzed as belonging to
the original application.

Michal


signature.asc
Description: Digital signature


Re: Not calling things twice in templates

2013-06-03 Thread Jonathan Slenders
Hi all. In the past, I once proposed a decorate template tag, but it was 
disapproved back then.
This would be another solution, to make the template language a lot more 
powerful.

1. First you define a decorator, for the behaviour you'd like to have. The 
"data" parameter indicates the receiving parameters.

{% define my_special_for "data" %}
{% if data %}

{% for i in data %}
{% placeholder %}
{% endfor %}

{% else %}
nothing found...
{% endif %}
{% enddefine %}


This definition can be used as follows:

{% decorate my_special_for data %}
{{ i.value }}
{% enddecorate %}


Not sure about the namings, but personally, I'm very convinced about this 
appoach. There shouldn't be too much logic in the template tags itself.

Another nice thing is that the  and  tags happen to be in exact 
the same scope which increases readability and the posibilities for 
automatic validation.

An extended version would create a second {% placeholder %} block for the 
"nothing found..." part.

If this is an acceptable appoach, I'm willing to contribute this to Django 
core, and write unit-tests and such.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Not calling things twice in templates

2013-06-03 Thread Jonathan Slenders
By the way, this could also be implemented using just files. The way {% 
include %} works for macros. If that's preferred. That becomes:


{% decorate "my_special_for.html" data %}
{{ i.value }}
{% enddecorate %}





Le lundi 3 juin 2013 13:38:29 UTC+2, Jonathan Slenders a écrit :
>
> Hi all. In the past, I once proposed a decorate template tag, but it was 
> disapproved back then.
> This would be another solution, to make the template language a lot more 
> powerful.
>
> 1. First you define a decorator, for the behaviour you'd like to have. The 
> "data" parameter indicates the receiving parameters.
>
> {% define my_special_for "data" %}
> {% if data %}
> 
> {% for i in data %}
> {% placeholder %}
> {% endfor %}
> 
> {% else %}
> nothing found...
> {% endif %}
> {% enddefine %}
>
>
> This definition can be used as follows:
>
> {% decorate my_special_for data %}
> {{ i.value }}
> {% enddecorate %}
>
>
> Not sure about the namings, but personally, I'm very convinced about this 
> appoach. There shouldn't be too much logic in the template tags itself.
>
> Another nice thing is that the  and  tags happen to be in exact 
> the same scope which increases readability and the posibilities for 
> automatic validation.
>
> An extended version would create a second {% placeholder %} block for the 
> "nothing found..." part.
>
> If this is an acceptable appoach, I'm willing to contribute this to Django 
> core, and write unit-tests and such.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Make sure QuerySet.get() does not fetch more rows than it absolutely needs

2013-06-03 Thread Patryk Zawadzki
Here's the ticket:

https://code.djangoproject.com/ticket/6785

tl;dr: Calling .get() on a badly filtered queryset can result in lots
of database rows being fetched and wrapped in Python objects for no
gain.

Currently .get() logic is as follows: clone the queryset, prepopulate
its full cache, check if more than one row was returned and if so,
raise MultipleObjectsReturned.

This works fine if the query returns two or five rows. It's not so
fine if the query results in thousands or millions of rows being
returned. While working on a large online store we had one of the
production servers die while trying to fetch twenty something million
rows because of a programming error that resulted in wrong Q object
being used as a filter.

The only reason all rows are fetched is to return an accurate counter
as part of the exception message. This counter is not accessible
programmatically and having the exact number there is of little value.
The ticket proposes to add a safeguard by limiting the database to at
most two results. The logic then is simple: if zero rows are returned,
raise ObjectDoesNotExist, if two, raise MultipleObjectsReturned. The
latter could possibly execute a second COUNT query if DEBUG is enabled
and the counter is deemed important enough to keep.

Of course you can work around the whole problem by not writing buggy
code but we all know how it works. In the mentioned case even unit
tests did not help as there were not enough records in the database to
trigger MultipleObjectsReturned.

Related pull request: https://github.com/django/django/pull/1139

-- 
Patryk Zawadzki
I solve problems.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Why apps have to have unique names? [related with subapps and name collision]

2013-06-03 Thread Patryk Zawadzki
Related 
thread: 
https://groups.google.com/d/topic/django-developers/9piN0wRFbLs/discussion

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: RFC: "universal" view decorators

2013-06-03 Thread gavinwahl
Attempting to make decorators anticipate every usage is the wrong approach. 
In Django, the sole interface to a view is as a callable that accepts an 
`HttpRequest` and turns it into an `HttpResponse` or exception. Django the 
framework doesn't actually need to support class-based views--because CBVs 
are just another way to build view callables.

View callables are an elegant abstraction that keeps the core of Django, 
and the decorators it provides, simple. Trying to anticipate all the ways 
of building view callables is not only complex, it is impossible. Why 
shouldn't I be able to use the built-in decorators with my own 
implementations of class-based views? If the built-in decorators' 
implementations are simple, I will be able to provide an adapter to use 
them with my CBV system. There are many useful decorators built-in to 
Django and in the wild, and my adapter will work with all of them, because 
they treat views as simple callables.

`method_decorator` is the right idea, but it is painful to use. It requires 
a tedious empty `dispatch` method, just to have something to decorate. 
Using decorators to modify views makes sense, because decoration is the 
only way to modify the functionality of a callable. Classes, however, have 
much more powerful ways of adding optional functionality: multiple 
inheritance.


# `DecoratorMixin`

`DecoratorMixin` is a class factory that converts any view decorator into a 
class-based view mixin. It works as you would expect with inheritance--MRO 
provides the same ordering that function decorators do, and multiple 
inheritance allows the mixins to be composed naturally. Inheriting from a 
decorated view decorates the subclass as you would expect. It averts the 
need for the annoying empty `dispatch` method in each class that wants to 
use a decorator.

Its implementation is simple: https://gist.github.com/gavinwahl/5694349. 
This is a complete implementation, and is all that's necessary to use view 
decorators with Django's CBVs. I use this code in all my projects with 
great success. [Here is an 
example](https://github.com/fusionbox/django-authtools/blob/master/authtools/views.py#L94)
 
of its use in a reimplementation of Django's auth views as CBVs.

Using it is easy and intuitive:

LoginRequiredMixin = DecoratorMixin(login_required)
 
class LoginRequiredAndCsrfMixin(DecoratorMixin(login_required),
DecoratorMixin(csrf_protect)):
"""
Inheriting from this class is the same as decorating your view 
thus::

@login_required
@csrf_protect
def someview(request):
pass
"""
pass

class SomeView(LoginRequiredMixin, View):
# ...
   
   
I propose `DecoratorMixin` be added to Django. It retains compatibility 
with all existing decorators, elegantly adapts functional decorators to 
good object-oriented practices, and has a simple implementation. 
'Universal' decorators don't accommodate existing third-party code, contain 
complex magic, and annul one of the most elegant principles of Django: 
views are simply callables.


On Thursday, September 15, 2011 2:44:39 PM UTC-6, Jacob Kaplan-Moss wrote:
>
> Hi folks --
>
> I'd like to convert all the view decorators built into Django to be
> "universal" -- so they'll work to decorate *any* view, whether a
> function, method, or class. I believe I've figured out a technique for
> this, but I'd like some feedback on the approach before I dive in too
> deep.
>
> Right now view decorators (e.g. @login_required) only work on
> functions. If you want to use a decorator on a method then you need to
> "convert" the decorator using method_decorator(original_decorator).
> You can't use view decorators on class-based views at all. This means
> making a class-based view require login requires this awesomeness::
>
> class MyView(View):
> @method_decorator(login_required)
> def dispatch(self, *args, **kwargs):
> return super(MyView, self.dispatch(*args, **kwargs)
>
> This makes me sad. It's really counter-intuitive and relies on a
> recognizing that functions and methods are different to even know to
> look for method_decorator.
>
> #14512 proposes a adding another view-decorator-factory for decorating
> class-based views, which would turn the above into::
>
> @class_view_decorator(login_required)
> class MyView(View):
> ...
>
> This makes me less sad, but still sad. Factory functions. Ugh.
>
> I want @login_required to work for anything::
>
> @login_required
> class MyView(View):
> ...
>
> class Something(object):
> @login_required
> def my_view(self, request):
> ...
>
> @login_required
> def my_view(request):
> ...
>
>
> Now, back in the day we somewhat had this: decorators tried to work
> with both functions and methods. The technique turned out not to work
> (

Username Independence in Auth Forms

2013-06-03 Thread gavinwahl
Some of the built-in auth forms only work on user models whose 
`USERNAME_FIELD` is `username`. It is possible to remove this constraint 
and allow them work on any user model. [django-authtools][1] demonstrates 
this possibility.

The two forms in question are `UserCreationForm` and `UserChangeForm`. 
 Both of them explicitly add a `username` field instead of letting the 
ModelForm add it automatically. For `UserChangeForm`, simply removing the 
`username` field from the form achieves user-model independence. 
`UserCreationForm` is slightly more complicated, due to the 
`clean_username` method. `clean_*` methods have to be named after their 
field, so it's hard to add one when you don't know the name of the field. 
This can be overcome by adding a validator to the field while initializing 
the form [2].

The reason the forms do have a `username` field currently is to change the 
help text, validation error messages, and validators. I don't think this 
should happen in the form, because all of these can be set on the model 
field instead. This could cause a backwards-compatibility concern if 
someone wasn't validating usernames in their custom User model (they are 
already validated in `auth.User`), and relied on the form instead. I don't 
think this is a serious issue--it only occurs if someone is using a custom 
User model, using the built-in forms, and not doing any username validation 
in their model.

If this approach sounds reasonable, I will submit it in the form of a patch.

[1]: 
https://github.com/fusionbox/django-authtools/blob/master/authtools/forms.py
[2]: 
https://github.com/fusionbox/django-authtools/blob/master/authtools/forms.py#L61

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Username Independence in Auth Forms

2013-06-03 Thread Aymeric Augustin
On 3 juin 2013, at 20:01, gavinw...@gmail.com wrote:

> Some of the built-in auth forms only work on user models whose 
> `USERNAME_FIELD` is `username`.

Hi Gavin,

The current code assumes that if you write a custom model, you'll also write 
the corresponding custom forms.

You may want to have a look at https://code.djangoproject.com/ticket/19353 
which describes the same problem (as far as I can tell).

-- 
Aymeric.




-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Username Independence in Auth Forms

2013-06-03 Thread Gavin Wahl
> The current code assumes that if you write a custom model, you'll also
write the corresponding custom forms.

Right. This is what I am proposing be fixed.


On Mon, Jun 3, 2013 at 12:31 PM, Aymeric Augustin <
aymeric.augus...@polytechnique.org> wrote:

> On 3 juin 2013, at 20:01, gavinw...@gmail.com wrote:
>
> > Some of the built-in auth forms only work on user models whose
> `USERNAME_FIELD` is `username`.
>
> Hi Gavin,
>
> The current code assumes that if you write a custom model, you'll also
> write the corresponding custom forms.
>
> You may want to have a look at 
> https://code.djangoproject.com/ticket/19353which describes the same problem 
> (as far as I can tell).
>
> --
> Aymeric.
>
>
>
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Django developers" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/django-developers/XxaZ50SxPj4/unsubscribe?hl=en
> .
> To unsubscribe from this group and all its topics, send an email to
> django-developers+unsubscr...@googlegroups.com.
> To post to this group, send email to django-developers@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-developers?hl=en
> .
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Make sure QuerySet.get() does not fetch more rows than it absolutely needs

2013-06-03 Thread Shai Berger
On Monday 03 June 2013, Patryk Zawadzki wrote:
> Here's the ticket:
> 
> https://code.djangoproject.com/ticket/6785
> 
> tl;dr: Calling .get() on a badly filtered queryset can result in lots
> of database rows being fetched and wrapped in Python objects for no
> gain.
> 

tl;dr: There's a general, valuable optimization to be made here, but it should 
be implemented at a lower level.

I have raised a related issue about a year and a half ago[0], thinking 
(mistakenly) that it was mostly an Oracle issue. Ian Kelly had pointed me in 
the right direction, but then life happened... The problem is that for all 
single-row queries except aggregates, Django uses the same strategy as used in 
get (and which you kept using in your patch): limit the query (usually) 
properly, then fetch until no more records are retrieved (fetching in done in 
chunks using fetchmany(), and not using fetchall()).

For single-row queries, this means two fetches; an unnecessary network 
roundtrip, for each such query, unless the backend or underlying driver take 
care to prevent it. On Oracle, at least, nobody does.

What we should do instead, in my opinion, is stop fetching as soon as a chunk 
arrives that isn't full. This alone should reduce the number of network 
accesses significantly on most Django projects.

While we're doing that, we could also define a new mode of sql execution (see 
SQLCompiler.results_iter(), in django.db.models.sql.compiler): Next to the 
current SINGLE (which uses fetchone()) and MULTI (the chunked loop described 
above) we could have SINGLE_VERIFY, which always fetches a single chunk of 
size 2. Make get() use that, and #6785 is fixed, while improving performance -- 
rather than hurting it on correct usage, like the proposed patch[1] does.

Assuming nobody raises objections, I intend to propose a patch along these 
lines sometime in the coming weeks (it's one of a few things on my to-do 
list), but I wouldn't mind at all if someone beat me to it.

Hope this helps,
Shai.

[0] https://groups.google.com/d/msg/django-developers/SQ0Pltt_f0M/3ccQn0aauiEJ
[1] https://github.com/django/django/pull/1139

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Not calling things twice in templates

2013-06-03 Thread Shai Berger
Hi,

On Monday 03 June 2013, Andre Terra wrote:
> Well, Russ, you asked for suggestions, so here's a couple half-hearted
> attempts.
> 

... and here's a couple of other ones, mostly inspired by those:

> {% with my_bonnet.bees as bees if my_bonnet.bees %}
> {% if my_bonnet.bees with my_bonnet.bees as bees %}

The only problem I see with these is the repetition -- we could just allow 
"as" on {% if %}:

{% if my_bonnet.bees as bees %}
 
 {% for bee in bees %}
 {{ bee }}
 {% endfor %}
 
{% else %}
 No bees!
{% endif %}

Another (halfbaked) idea: Allow separating the "in" from the {% for %}. Let a 
{% for %} with no "in"  make a collection "current", and then its elements can 
be iterated over by, say, {% each %}:

{% for my_bonnet.bees %}
 
 {% each bee %}
 {{ bee }}
 {% endeach %}
 
{% empty %}
 No bees!
{% endfor %}

The problem I see with this: it's perhaps a tad too implicit.

HTH,
Shai.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[GSoC] Revamping validation framework and merging django-secure once again

2013-06-03 Thread Christopher Medrela
Hello!

I'm really happy that I've been accepted as a Google Summer of Code 
student. I
will work at revamping validation framework and merging django-secure this
summer. I created this thread to start discussion (especially about public
API) and get some feedback as well as to share progress. Any comments are
welcomed!

You can find my proposal as a gist here [1], but I'm going to describe my
ideas in short here.

[1] https://gist.github.com/chrismedrela/82cbda8d2a78a280a129

My proposal consists of two parts: the first one is revamping validation
framework. Don't be confused with form validation - I mean validation of
(mainly) apps and models triggered before launching server (or directly by
`python manage.py validate` command). The main drawback of the existing
framework is that it's monolithic and therefore hard to customize. The 
second
part of my project is merging django-secure using the new refactored
framework. That will be a proof that the framework is customizable.

Let's start with validation. The validation is done every time you run your
Django application. It prevents from misconfigurations (for example missing
`upload_to` attribute of FieldFile) or invalid models (a model with a `id`
field without `primary_key` set to True). Some apps need custom validation,
for example admin app need to check all registered ModelAdmin instances. The
new validation framework will cover some other use cases. For example, your
apps will be able to check dependencies.

Let's start with validating a field. Consider existing FieldFile field. It
requires an `upload_to` attribute. How could you check if it's set using the
new framework?

class FieldFile(Field):
(... lots of stuff ...)

def validate_upload_to(self):
if not self.upload_to:
yield Error(obj=self, msg="required 'upload_to' attribute",
explanation="Django need to know the directory where 
uploaded files should be stored.",
hint="Add \"upload_to = 'path/to/directory/on/server'\" to 
model %(model)s in file %(model_file)s.")

All methods starting with `validate_` will be called automagically at
validation stage. You don't have to trigger it manually. The methods 
shouldn't
have any parameters (excluding `self`). They should return list of errors 
and
warnings or they should yield each of them (like in the example).

You can see a new `Error` structure with the following fields: `obj`, `msg`,
`explanation` and `hint`. The last two attributes are separated from `msg` 
in
order to force Django developers to give its users really useful,
user-friendly error messages with a list of solutions and explanation of a
problem. I think that Django should be an intelligent framework that make a
conversation with its users.

The new framework will introduce a concept of warnings which are really
similar to errors expect that they allow you to run server. A warning have 
the
same fields: `obj`, `msg`, `explanation` and `hint`. Warnings will be used
while merging django-secure.

Not only fields can be validated, but also: models, managers and apps. In 
case
of models, a developer has to write a *class method*, because we validate a
model which is a class, not an instance. In case of apps, you can create
`validation.py` file which should contain functions.

After refactoring validation framework, I will focus on merging 
django-secure.
django-secure is a set of tests improving security of django applications. I
won't implement new features, that would be only fitting it to the new
framework. I will publish proposal of its new public API in the future.

Feel free to comment and criticize!

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [GSoC] Revamping validation framework and merging django-secure once again

2013-06-03 Thread Carl Meyer
Hi Christopher,

Overall, this looks like a great project and I look forward to the more
flexible validation hooks. As the author of django-secure, I do have one
concern with the implementation plan:

Django's existing validation checks are intended to be run in
development, as a debugging aid, but not in production (to avoid any
slowdown). Thus, by default they are run prior to many management
commands (such as syncdb, runserver), but are generally not run on
production deployments.

The checks in django-secure, on the other hand, are intended to be run
only under your production configuration, and are mostly useless/wrong
in development. Since runserver doesn't handle HTTPS, most people don't
use HTTPS in development, which means you can't set e.g.
SESSION_COOKIE_SECURE to True in development or your sessions will
break, which means that django-secure check will fail; same goes for
most of the other checks. Running django-secure's checks every time you
syncdb or runserver in development would be at best a waste of time and
at worst extremely annoying.

So I think the validation framework you build has to incorporate some
kind of distinction between these two types of validation, which have
very different purposes and should be run at different times:
development/debugging validation and production-configuration
validation. I'm not sure exactly what form this distinction should take:
perhaps validators are simply tagged as one type or the other and then
there are two different management commands?

Interested in your thoughts,

Carl

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Not calling things twice in templates

2013-06-03 Thread Jonathan Slenders
We don't even have to change the for-syntax:

{% for bee in my_bonnet.bees %} 
  
 {% loop %} 
 {{ bee }} 
 {% endloop %} 
  
{% empty %} 
 No bees! 
{% endfor %}



Le mardi 4 juin 2013 00:03:12 UTC+2, Shai Berger a écrit :
>
>
> {% for my_bonnet.bees %} 
>   
>  {% each bee %} 
>  {{ bee }} 
>  {% endeach %} 
>   
> {% empty %} 
>  No bees! 
> {% endfor %} 
>

 

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Make sure QuerySet.get() does not fetch more rows than it absolutely needs

2013-06-03 Thread Anssi Kääriäinen
On 4 kesä, 00:22, Shai Berger  wrote:
> On Monday 03 June 2013, Patryk Zawadzki wrote:
>
> > Here's the ticket:
>
> >https://code.djangoproject.com/ticket/6785
>
> > tl;dr: Calling .get() on a badly filtered queryset can result in lots
> > of database rows being fetched and wrapped in Python objects for no
> > gain.
>
> tl;dr: There's a general, valuable optimization to be made here, but it should
> be implemented at a lower level.
>
> I have raised a related issue about a year and a half ago[0], thinking
> (mistakenly) that it was mostly an Oracle issue. Ian Kelly had pointed me in
> the right direction, but then life happened... The problem is that for all
> single-row queries except aggregates, Django uses the same strategy as used in
> get (and which you kept using in your patch): limit the query (usually)
> properly, then fetch until no more records are retrieved (fetching in done in
> chunks using fetchmany(), and not using fetchall()).
>
> For single-row queries, this means two fetches; an unnecessary network
> roundtrip, for each such query, unless the backend or underlying driver take
> care to prevent it. On Oracle, at least, nobody does.
>
> What we should do instead, in my opinion, is stop fetching as soon as a chunk
> arrives that isn't full. This alone should reduce the number of network
> accesses significantly on most Django projects.
>
> While we're doing that, we could also define a new mode of sql execution (see
> SQLCompiler.results_iter(), in django.db.models.sql.compiler): Next to the
> current SINGLE (which uses fetchone()) and MULTI (the chunked loop described
> above) we could have SINGLE_VERIFY, which always fetches a single chunk of
> size 2. Make get() use that, and #6785 is fixed, while improving performance 
> --
> rather than hurting it on correct usage, like the proposed patch[1] does.
>
> Assuming nobody raises objections, I intend to propose a patch along these
> lines sometime in the coming weeks (it's one of a few things on my to-do
> list), but I wouldn't mind at all if someone beat me to it.
>
> Hope this helps,
>         Shai.
>
> [0]https://groups.google.com/d/msg/django-developers/SQ0Pltt_f0M/3ccQn0a...
> [1]https://github.com/django/django/pull/1139

Note that how queryset iteration happens has been changed[1]. Except
for .iterator() call the rows in the queryset are converted to objects
immediately. This isn't a big change for other core backends than
Oracle (they always fetched all rows in one go), but for Oracle users
this could mean changes in amount of rows fetched from DB.

So, with this in mind you could change the compiler's iterator to use
fetchall() except when .iterator() is used.

As for .get() - I don't find the number of duplicates in the error
message that useful. If you got more than one object you failed. How
badly you failed isn't interesting. I can't think of any case where
the amount of objects you got actually matters. If somebody feels
strongly about this, then we could limit the amount of fetched objects
to some smallish amount (21 for example). If you actually get 21
objects back then you say "it returned more than 20" in the error
message.

 - Anssi

[1]https://code.djangoproject.com/ticket/18702

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.