Ticket #9033: 9033.diff

File 9033.diff, 13.7 KB (added by Derek Willis, 14 years ago)
  • docs/ref/models/querysets.txt

    From 076d59d274808398ea3c29976301c5ae0ca3da61 Mon Sep 17 00:00:00 2001
    From: Derek Willis <dwillis@gmail.com>
    Date: Sat, 18 Sep 2010 22:06:04 -0400
    Subject: [PATCH] better display of QuerySet.extra() argument docs
    
    ---
     docs/ref/models/querysets.txt |  216 ++++++++++++++++++++--------------------
     1 files changed, 108 insertions(+), 108 deletions(-)
    
    diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
    index 87680d3..d5be956 100644
    a b principle, so you should avoid them if possible.  
    689689Specify one or more of ``params``, ``select``, ``where`` or ``tables``. None
    690690of the arguments is required, but you should use at least one of them.
    691691
    692 ``select``
    693     The ``select`` argument lets you put extra fields in the ``SELECT`` clause.
    694     It should be a dictionary mapping attribute names to SQL clauses to use to
    695     calculate that attribute.
     692    * ``select``
     693        The ``select`` argument lets you put extra fields in the ``SELECT`` clause.
     694        It should be a dictionary mapping attribute names to SQL clauses to use to
     695        calculate that attribute.
    696696
    697     Example::
     697        Example::
    698698
    699         Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
    700 
    701     As a result, each ``Entry`` object will have an extra attribute,
    702     ``is_recent``, a boolean representing whether the entry's ``pub_date`` is
    703     greater than Jan. 1, 2006.
     699            Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
     700
     701        As a result, each ``Entry`` object will have an extra attribute,
     702        ``is_recent``, a boolean representing whether the entry's ``pub_date`` is
     703        greater than Jan. 1, 2006.
    704704
    705     Django inserts the given SQL snippet directly into the ``SELECT``
    706     statement, so the resulting SQL of the above example would be something
    707     like::
     705        Django inserts the given SQL snippet directly into the ``SELECT``
     706        statement, so the resulting SQL of the above example would be something
     707        like::
    708708
    709         SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
    710         FROM blog_entry;
     709            SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
     710            FROM blog_entry;
    711711
    712712
    713     The next example is more advanced; it does a subquery to give each
    714     resulting ``Blog`` object an ``entry_count`` attribute, an integer count
    715     of associated ``Entry`` objects::
     713        The next example is more advanced; it does a subquery to give each
     714        resulting ``Blog`` object an ``entry_count`` attribute, an integer count
     715        of associated ``Entry`` objects::
    716716
    717         Blog.objects.extra(
    718             select={
    719                 'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
    720             },
    721         )
     717            Blog.objects.extra(
     718                select={
     719                    'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
     720                },
     721            )
    722722
    723     (In this particular case, we're exploiting the fact that the query will
    724     already contain the ``blog_blog`` table in its ``FROM`` clause.)
     723        (In this particular case, we're exploiting the fact that the query will
     724        already contain the ``blog_blog`` table in its ``FROM`` clause.)
    725725
    726     The resulting SQL of the above example would be::
     726        The resulting SQL of the above example would be::
    727727
    728         SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
    729         FROM blog_blog;
     728            SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
     729            FROM blog_blog;
    730730
    731     Note that the parenthesis required by most database engines around
    732     subqueries are not required in Django's ``select`` clauses. Also note that
    733     some database backends, such as some MySQL versions, don't support
    734     subqueries.
     731        Note that the parenthesis required by most database engines around
     732        subqueries are not required in Django's ``select`` clauses. Also note that
     733        some database backends, such as some MySQL versions, don't support
     734        subqueries.
    735735
    736     .. versionadded:: 1.0
     736        .. versionadded:: 1.0
    737737
    738     In some rare cases, you might wish to pass parameters to the SQL fragments
    739     in ``extra(select=...)``. For this purpose, use the ``select_params``
    740     parameter. Since ``select_params`` is a sequence and the ``select``
    741     attribute is a dictionary, some care is required so that the parameters
    742     are matched up correctly with the extra select pieces.  In this situation,
    743     you should use a ``django.utils.datastructures.SortedDict`` for the
    744     ``select`` value, not just a normal Python dictionary.
     738        In some rare cases, you might wish to pass parameters to the SQL fragments
     739        in ``extra(select=...)``. For this purpose, use the ``select_params``
     740        parameter. Since ``select_params`` is a sequence and the ``select``
     741        attribute is a dictionary, some care is required so that the parameters
     742        are matched up correctly with the extra select pieces.  In this situation,
     743        you should use a ``django.utils.datastructures.SortedDict`` for the
     744        ``select`` value, not just a normal Python dictionary.
    745745
    746     This will work, for example::
     746        This will work, for example::
    747747
    748         Blog.objects.extra(
    749             select=SortedDict([('a', '%s'), ('b', '%s')]),
    750             select_params=('one', 'two'))
     748            Blog.objects.extra(
     749                select=SortedDict([('a', '%s'), ('b', '%s')]),
     750                select_params=('one', 'two'))
    751751
    752     The only thing to be careful about when using select parameters in
    753     ``extra()`` is to avoid using the substring ``"%%s"`` (that's *two*
    754     percent characters before the ``s``) in the select strings. Django's
    755     tracking of parameters looks for ``%s`` and an escaped ``%`` character
    756     like this isn't detected. That will lead to incorrect results.
     752        The only thing to be careful about when using select parameters in
     753        ``extra()`` is to avoid using the substring ``"%%s"`` (that's *two*
     754        percent characters before the ``s``) in the select strings. Django's
     755        tracking of parameters looks for ``%s`` and an escaped ``%`` character
     756        like this isn't detected. That will lead to incorrect results.
    757757
    758 ``where`` / ``tables``
    759     You can define explicit SQL ``WHERE`` clauses -- perhaps to perform
    760     non-explicit joins -- by using ``where``. You can manually add tables to
    761     the SQL ``FROM`` clause by using ``tables``.
     758    * ``where`` / ``tables``
     759        You can define explicit SQL ``WHERE`` clauses -- perhaps to perform
     760        non-explicit joins -- by using ``where``. You can manually add tables to
     761        the SQL ``FROM`` clause by using ``tables``.
    762762
    763     ``where`` and ``tables`` both take a list of strings. All ``where``
    764     parameters are "AND"ed to any other search criteria.
     763        ``where`` and ``tables`` both take a list of strings. All ``where``
     764        parameters are "AND"ed to any other search criteria.
    765765
    766     Example::
     766        Example::
    767767
    768         Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])
     768            Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])
    769769
    770     ...translates (roughly) into the following SQL::
     770        ...translates (roughly) into the following SQL::
    771771
    772         SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);
     772            SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);
    773773
    774     Be careful when using the ``tables`` parameter if you're specifying
    775     tables that are already used in the query. When you add extra tables
    776     via the ``tables`` parameter, Django assumes you want that table included
    777     an extra time, if it is already included. That creates a problem,
    778     since the table name will then be given an alias. If a table appears
    779     multiple times in an SQL statement, the second and subsequent occurrences
    780     must use aliases so the database can tell them apart. If you're
    781     referring to the extra table you added in the extra ``where`` parameter
    782     this is going to cause errors.
     774        Be careful when using the ``tables`` parameter if you're specifying
     775        tables that are already used in the query. When you add extra tables
     776        via the ``tables`` parameter, Django assumes you want that table included
     777        an extra time, if it is already included. That creates a problem,
     778        since the table name will then be given an alias. If a table appears
     779        multiple times in an SQL statement, the second and subsequent occurrences
     780        must use aliases so the database can tell them apart. If you're
     781        referring to the extra table you added in the extra ``where`` parameter
     782        this is going to cause errors.
    783783
    784     Normally you'll only be adding extra tables that don't already appear in
    785     the query. However, if the case outlined above does occur, there are a few
    786     solutions. First, see if you can get by without including the extra table
    787     and use the one already in the query. If that isn't possible, put your
    788     ``extra()`` call at the front of the queryset construction so that your
    789     table is the first use of that table. Finally, if all else fails, look at
    790     the query produced and rewrite your ``where`` addition to use the alias
    791     given to your extra table. The alias will be the same each time you
    792     construct the queryset in the same way, so you can rely upon the alias
    793     name to not change.
     784        Normally you'll only be adding extra tables that don't already appear in
     785        the query. However, if the case outlined above does occur, there are a few
     786        solutions. First, see if you can get by without including the extra table
     787        and use the one already in the query. If that isn't possible, put your
     788        ``extra()`` call at the front of the queryset construction so that your
     789        table is the first use of that table. Finally, if all else fails, look at
     790        the query produced and rewrite your ``where`` addition to use the alias
     791        given to your extra table. The alias will be the same each time you
     792        construct the queryset in the same way, so you can rely upon the alias
     793        name to not change.
    794794
    795 ``order_by``
    796     If you need to order the resulting queryset using some of the new fields
    797     or tables you have included via ``extra()`` use the ``order_by`` parameter
    798     to ``extra()`` and pass in a sequence of strings. These strings should
    799     either be model fields (as in the normal ``order_by()`` method on
    800     querysets), of the form ``table_name.column_name`` or an alias for a column
    801     that you specified in the ``select`` parameter to ``extra()``.
     795    * ``order_by``
     796        If you need to order the resulting queryset using some of the new fields
     797        or tables you have included via ``extra()`` use the ``order_by`` parameter
     798        to ``extra()`` and pass in a sequence of strings. These strings should
     799        either be model fields (as in the normal ``order_by()`` method on
     800        querysets), of the form ``table_name.column_name`` or an alias for a column
     801        that you specified in the ``select`` parameter to ``extra()``.
    802802
    803     For example::
     803        For example::
    804804
    805         q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
    806         q = q.extra(order_by = ['-is_recent'])
     805            q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
     806            q = q.extra(order_by = ['-is_recent'])
    807807
    808     This would sort all the items for which ``is_recent`` is true to the front
    809     of the result set (``True`` sorts before ``False`` in a descending
    810     ordering).
     808        This would sort all the items for which ``is_recent`` is true to the front
     809        of the result set (``True`` sorts before ``False`` in a descending
     810        ordering).
    811811
    812     This shows, by the way, that you can make multiple calls to
    813     ``extra()`` and it will behave as you expect (adding new constraints each
    814     time).
     812        This shows, by the way, that you can make multiple calls to
     813        ``extra()`` and it will behave as you expect (adding new constraints each
     814        time).
    815815
    816 ``params``
    817     The ``where`` parameter described above may use standard Python database
    818     string placeholders -- ``'%s'`` to indicate parameters the database engine
    819     should automatically quote. The ``params`` argument is a list of any extra
    820     parameters to be substituted.
     816    * ``params``
     817        The ``where`` parameter described above may use standard Python database
     818        string placeholders -- ``'%s'`` to indicate parameters the database engine
     819        should automatically quote. The ``params`` argument is a list of any extra
     820        parameters to be substituted.
    821821
    822     Example::
     822        Example::
    823823
    824         Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
     824            Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    825825
    826     Always use ``params`` instead of embedding values directly into ``where``
    827     because ``params`` will ensure values are quoted correctly according to
    828     your particular backend. (For example, quotes will be escaped correctly.)
     826        Always use ``params`` instead of embedding values directly into ``where``
     827        because ``params`` will ensure values are quoted correctly according to
     828        your particular backend. (For example, quotes will be escaped correctly.)
    829829
    830     Bad::
     830        Bad::
    831831
    832         Entry.objects.extra(where=["headline='Lennon'"])
     832            Entry.objects.extra(where=["headline='Lennon'"])
    833833
    834     Good::
     834        Good::
    835835
    836         Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
     836            Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    837837
    838838``defer(*fields)``
    839839~~~~~~~~~~~~~~~~~~
Back to Top