Skip to content

Commit 9bbf79c

Browse files
committed
Merge branch 'master' into releases/1.2.x
2 parents 0903ff9 + 3432d81 commit 9bbf79c

16 files changed

Lines changed: 202 additions & 233 deletions

README.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ Features
2828
* **Reliable** - more than 300 test cases and counting. |coverage| |build|
2929
* **Compatible** with Django 1.4 to 1.8, running Python 2.7, 3.3 or 3.4.
3030

31+
Django-hvad also features support for `Django REST framework`_ 3.1 or newer, including
32+
translation-aware serializers.
33+
3134
Example Uses
3235
------------
3336

@@ -133,6 +136,7 @@ Jonas Obrist (https://github.com/ojii) for making django-nani and for helping me
133136
.. _release notes: https://django-hvad.readthedocs.org/en/latest/public/release_notes.html
134137
.. _issue tracker: https://github.com/KristianOellegaard/django-hvad/issues
135138
.. _PyPI: https://pypi.python.org/pypi/django-hvad
139+
.. _Django REST framework: http://www.django-rest-framework.org/
136140
.. _installation guide: http://django-hvad.readthedocs.org/en/latest/public/installation.html
137141
.. _quickstart guide: http://django-hvad.readthedocs.org/en/latest/public/quickstart.html
138142

docs/conf.py

Lines changed: 14 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
# All configuration values have a default; values that are commented out
1212
# serve to show the default.
1313

14-
import sys, os
14+
import sys, os, sphinx
15+
16+
readthedocs = os.environ.get('READTHEDOCS', None) == 'True'
1517

1618
# If extensions (or modules to document with autodoc) are in another directory,
1719
# add these directories to sys.path here. If the directory is relative to the
@@ -23,156 +25,51 @@
2325

2426
# -- General configuration -----------------------------------------------------
2527

26-
# If your documentation needs a minimal Sphinx version, state it here.
27-
#needs_sphinx = '1.0'
28-
29-
# Add any Sphinx extension module names here, as strings. They can be extensions
30-
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
31-
extensions = ['sphinx.ext.intersphinx', 'djangodocs', 'github']
28+
extensions = [
29+
'sphinx.ext.intersphinx',
30+
'djangodocs',
31+
'github'
32+
]
3233
intersphinx_mapping = {
3334
'python': ('http://docs.python.org/2.7', None),
3435
'django': ('http://readthedocs.org/docs/django/en/latest/', None),
3536
}
3637

37-
# Add any paths that contain templates here, relative to this directory.
3838
templates_path = ['_templates']
39-
40-
# The suffix of source filenames.
4139
source_suffix = '.rst'
42-
43-
# The encoding of source files.
44-
#source_encoding = 'utf-8-sig'
45-
46-
# The master toctree document.
40+
exclude_patterns = ['_build']
4741
master_doc = 'index'
4842

4943
# General information about the project.
5044
project = u'django-hvad'
5145
copyright = u'2011-2015, Kristian Øllegaard, Jonas Obrist & contributors'
5246

53-
# The version info for the project you're documenting, acts as replacement for
54-
# |version| and |release|, also used in various other places throughout the
55-
# built documents.
56-
#
57-
# The short X.Y version.
5847
version = '1.2'
59-
# The full version, including alpha/beta/rc tags.
6048
release = '1.2.0'
6149

62-
# The language for content autogenerated by Sphinx. Refer to documentation
63-
# for a list of supported languages.
64-
#language = None
65-
66-
# There are two options for replacing |today|: either, you set today to some
67-
# non-false value, then it is used:
68-
#today = ''
69-
# Else, today_fmt is used as the format for a strftime call.
70-
#today_fmt = '%B %d, %Y'
71-
72-
# List of patterns, relative to source directory, that match files and
73-
# directories to ignore when looking for source files.
74-
exclude_patterns = ['_build']
75-
76-
# The reST default role (used for this markup: `text`) to use for all documents.
77-
#default_role = None
78-
79-
# If true, '()' will be appended to :func: etc. cross-reference text.
80-
#add_function_parentheses = True
81-
82-
# If true, the current module name will be prepended to all description
83-
# unit titles (such as .. function::).
84-
#add_module_names = True
85-
86-
# If true, sectionauthor and moduleauthor directives will be shown in the
87-
# output. They are ignored by default.
88-
#show_authors = False
8950

9051
# The name of the Pygments (syntax highlighting) style to use.
9152
pygments_style = 'trac'
9253

93-
# A list of ignored prefixes for module index sorting.
94-
#modindex_common_prefix = []
95-
96-
9754
# -- Options for HTML output ---------------------------------------------------
9855

99-
# The theme to use for HTML and HTML Help pages. See the documentation for
100-
# a list of builtin themes.
101-
html_theme = 'classic'
102-
103-
# Theme options are theme-specific and customize the look and feel of a theme
104-
# further. For a list of options available for each theme, see the
105-
# documentation.
56+
if sphinx.version_info >= (1, 3):
57+
html_theme = 'default' if readthedocs else 'classic'
58+
else:
59+
html_theme = 'default'
10660
html_theme_options = {
10761
'externalrefs': True,
10862
}
10963

11064
html_style = 'stylesheet.css'
111-
112-
# Add any paths that contain custom themes here, relative to this directory.
113-
#html_theme_path = []
114-
115-
# The name for this set of Sphinx documents. If None, it defaults to
116-
# "<project> v<release> documentation".
117-
#html_title = None
118-
119-
# A shorter title for the navigation bar. Default is the same as html_title.
120-
#html_short_title = None
121-
122-
# The name of an image file (relative to this directory) to place at the top
123-
# of the sidebar.
124-
#html_logo = None
125-
126-
# The name of an image file (within the static path) to use as favicon of the
127-
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
128-
# pixels large.
129-
#html_favicon = None
130-
131-
# Add any paths that contain custom static files (such as style sheets) here,
132-
# relative to this directory. They are copied after the builtin static files,
133-
# so a file named "default.css" will overwrite the builtin "default.css".
13465
html_static_path = ['_static']
13566

136-
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
137-
# using the given strftime format.
138-
#html_last_updated_fmt = '%b %d, %Y'
139-
140-
# If true, SmartyPants will be used to convert quotes and dashes to
141-
# typographically correct entities.
14267
html_use_smartypants = True
68+
html_show_sourcelink = False
14369

14470
# Custom sidebar templates, maps document names to template names.
14571
html_sidebars = {'**': ['globaltoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html']}
14672

147-
# Additional templates that should be rendered to pages, maps page names to
148-
# template names.
149-
#html_additional_pages = {}
150-
151-
# If false, no module index is generated.
152-
#html_domain_indices = True
153-
154-
# If false, no index is generated.
155-
#html_use_index = True
156-
157-
# If true, the index is split into individual pages for each letter.
158-
#html_split_index = False
159-
160-
# If true, links to the reST sources are added to the pages.
161-
html_show_sourcelink = False
162-
163-
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
164-
#html_show_sphinx = True
165-
166-
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
167-
#html_show_copyright = True
168-
169-
# If true, an OpenSearch description file will be output, and all pages will
170-
# contain a <link> tag referring to it. The value of this option must be the
171-
# base URL from which the finished HTML is served.
172-
#html_use_opensearch = ''
173-
174-
# This is the file name suffix for HTML files (e.g. ".xhtml").
175-
#html_file_suffix = None
17673

17774
# Output file base name for HTML help builder.
17875
htmlhelp_basename = 'Projectdoc'
@@ -193,29 +90,6 @@
19390
u'Jonas Obrist & contributors', 'manual'),
19491
]
19592

196-
# The name of an image file (relative to this directory) to place at the top of
197-
# the title page.
198-
#latex_logo = None
199-
200-
# For "manual" documents, if this is true, then toplevel headings are parts,
201-
# not chapters.
202-
#latex_use_parts = False
203-
204-
# If true, show page references after internal links.
205-
#latex_show_pagerefs = False
206-
207-
# If true, show URL addresses after external links.
208-
#latex_show_urls = False
209-
210-
# Additional stuff for the LaTeX preamble.
211-
#latex_preamble = ''
212-
213-
# Documents to append as an appendix to all manuals.
214-
#latex_appendices = []
215-
216-
# If false, no module index is generated.
217-
#latex_domain_indices = True
218-
21993

22094
# -- Options for manual page output --------------------------------------------
22195

docs/internal/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ This part of the documentation is grouped by file, not by topic.
3131
forms
3232
manager
3333
models
34+
query
3435
utils

docs/internal/manager.rst

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,20 @@ FallbackQueryset
542542
A queryset that can optionally use fallbacks and by default only fetches the
543543
:term:`Shared Model`.
544544

545+
There are actually two underlying implementations, the ``LegacyFallbackQueryset``
546+
and the ``SelfJoinFallbackQueryset``. Implementation is chosen at initialization
547+
based on the ``HVAD_LEGACY_FALLBACKS`` setting. It defaults to ``False``
548+
(use SelfJoin) on Django 1.6 and newer, and ``True`` (use Legacy) on older
549+
versions.
550+
551+
The ``LegacyFallbackQueryset`` generates lots of queries as it walks through
552+
batches of models, fetches their translations and matches them onto the models.
553+
554+
The ``SelfJoinFallbackQueryset`` uses a single self outer join to achieve the same
555+
result in only one (complex) query. Performance is good as the number of items
556+
per model in the cross-product is limited to the number of languages that
557+
Django supports. Implementation digs deeper into Django internals, though.
558+
545559
.. attribute:: _translation_fallbacks
546560

547561
List of fallbacks to use (or ``None``).
@@ -571,26 +585,6 @@ FallbackQueryset
571585
Injects *translation_fallbacks* into *kwargs* and calls the superclass.
572586

573587

574-
**************************
575-
TranslationFallbackManager
576-
**************************
577-
578-
.. warning:: This class is deprecated and will be removed in next release.
579-
Please use :meth:`~hvad.manager.TranslationManager.untranslated`
580-
instead.
581-
582-
.. class:: TranslationFallbackManager
583-
584-
.. method:: use_fallbacks(self, *fallbacks)
585-
586-
Proxies to :meth:`FallbackQueryset.use_fallbacks` by calling
587-
:meth:`get_queryset` first.
588-
589-
.. method:: get_queryset(self)
590-
591-
Returns an instance of :class:`FallbackQueryset` for this manager.
592-
593-
594588
************************
595589
TranslationAwareQueryset
596590
************************
@@ -742,7 +736,9 @@ TranslationAwareQueryset
742736
object provided in *extra_filters* and returns a queryset from the
743737
superclass, so that the methods that call this method can directely
744738
access methods on the superclass to reduce boilerplate code.
745-
739+
740+
.. warning:: This internal method returns a ``super()`` proxy object,
741+
be sure to understand the implications before using it.
746742

747743
***********************
748744
TranslationAwareManager

docs/internal/query.rst

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#################
2+
:mod:`hvad.query`
3+
#################
4+
5+
.. module:: hvad.query
6+
7+
This modules containts abstractions for accessing some internal parts of Django
8+
ORM that are used in hvad. The intent is that anytime some code in hvad needs
9+
to access some Django internals, it should do so through a function in this module.
10+
11+
.. function:: query_terms(model, path)
12+
13+
This iterator yields all terms in the specified ``path``, along with full
14+
introspection data. Each term is output as a named tuple with the following
15+
members:
16+
17+
* ``depth``: how deep in the path is this term. Counted from zero.
18+
* ``term``: the term string.
19+
* ``model: `` the model the term is attached to. It will start with passed
20+
``model`` then walk through relations as terms are enumerated.
21+
* ``field``: the actual field, on the model, the term refers to.
22+
* ``translated``: whether the field is a translated field (True) or a shared fielf (False).
23+
* ``target``: the target model of the relation, or ``None`` if not a relational field.
24+
* ``many``: whether the target can be multiple (that is, it is a M2M or reverse FK).
25+
26+
If a field is not recognized, it is assumed the path is complete and everything
27+
that follows is a query expression (such as ``__year__in``). Query expression
28+
terms will be yielded with ``field`` set to ``None``.
29+
30+
.. function:: q_children(q)
31+
32+
Iterator that recursively yields all key-value pairs of a ``Q`` object. Each
33+
pair is yielded as a 3-tuple: the pair itself, its container and its index in
34+
the container. This allows modifying it.
35+
36+
.. function:: expression_nodes(expression)
37+
38+
Iterator that recursively yields all nodes in an expression tree.
39+
40+
.. function:: where_node_children(node)
41+
42+
Iterator that recursively yields all fields of a where node. It is used to
43+
determine whether a custom ``Q`` object included a ``language_code`` filter.

docs/internal/utils.rst

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242

4343
Returns the translation for an instance.
4444

45-
* If ``enforce`` is false, then ``language`` is used as a default language,
45+
* If ``enforce`` is False, then ``language`` is used as a default language,
4646
if the ``instance`` has no language currently loaded.
47-
* If ``enforce`` is true, then ``language`` will be enforced upon the
47+
* If ``enforce`` is True, then ``language`` will be enforced upon the
4848
translation, ignoring cached translation if it is not in the given
4949
language.
5050

@@ -66,11 +66,47 @@
6666
(meta) of Django models that raises a more useful exception when one tries
6767
to access translated fields with the wrong manager.
6868

69+
This descriptor is pending deprecation as the associated method is being
70+
removed from Django.
71+
6972
.. method:: __init__(self, real)
73+
74+
Retains a reference to the actual method this descriptor is replacing.
7075

7176
.. method:: __call__(self, meta, name)
7277

73-
.. function:: permissive_field_by_name(self, name)
74-
75-
Returns the field from the :term:`Shared Model` or
76-
:term:`Translations Model`, if it is on either.
78+
Catches improper use of the ``get_field_by_name`` method to access
79+
translated fields and raise a ``WrongManager`` exception.
80+
81+
.. class:: SmartGetField
82+
83+
Smart version of the standard :meth:`get_field` on the options
84+
(meta) of Django models that raises a more useful exception when one tries
85+
to access translated fields with the wrong manager.
86+
87+
.. method:: __init__(self, real)
88+
89+
Retains a reference to the actual method this descriptor is replacing.
90+
91+
.. method:: __call__(self, meta, name)
92+
93+
Catches improper use of the ``get_field`` method to access
94+
translated fields and raise a ``WrongManager`` exception.
95+
96+
.. class:: _MinimumDjangoVersionDescriptor
97+
98+
Helper class used by :func:`minimumDjangoVersion` decorator.
99+
100+
.. function:: minimumDjangoVersion(*args)
101+
102+
Decorator that will catch attempts to use methods on a Django version that
103+
does not support them and raise a helpful exception.
104+
105+
Arguments must be the minimum allowable Django version, the will be compared
106+
against the ``django.VERSION`` tuple.
107+
108+
.. function:: settings_updater(func):
109+
110+
Decorator for setting globals depending on Django settings. It simply invokes
111+
the decorated function immediately, then calls it again every time the
112+
``setting_changed`` signal is sent by Django.

0 commit comments

Comments
 (0)