Comment (by sephii):
To get this to work we need to change some low-level stuff since model
fields are stripped out by the metaclass to be put in Model._meta. Since
[http://www.sphinx-doc.org/en/stable/ext/autodoc.html Sphinx's autodoc
module allows to manually add members to a class] I think it would be
better to do in manually than trying to change the way Django models are
constructed.
Anyway, I came up with the following code that makes Sphinx's autodoc work
for Django models. It is '''very''' hackish and unsurprisingly makes some
tests fail, so I'm just putting this here for the record in case anyone
would want to take that over someday.
{{{
#!python
class ModelBase(type):
def __getattr__(self, attr):
if attr == '_meta':
raise AttributeError(attr)
try:
return self._meta.get_field(attr)
except FieldDoesNotExist:
raise AttributeError(attr)
@property
def __dict__(self):
try:
model_dict = {
f.name: f for f in self._meta.get_fields()
}
except AppRegistryNotReady:
model_dict = {}
model_dict.update(super(ModelBase, self).__dict__)
return model_dict
# Rest of ModelBase code...
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/12096#comment:10>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by Simon Charette):
Since `DeferredAttribute`
[https://github.com/django/django/commit/7f51876f99851fdc3fef63aecdfbcffa199c26b9
#diff-35c61cb049d39b2e890f12f8c1f9583fb8ca351a8495718b5375a7120f775d05R700
are systematically added as model class attributes] (#26207) this would be
a simple matter of adjusting a few `__get__(instance=None)` case to return
`self.field` (`DeferredAttribute` and the three classes of
`related_descriptors`).
The only remaining concern here is backward compatibility.
[https://github.com/django/django/blob/e30d6678421b7573a1995f61521f14348c9b2a17/django/db/models/fields/related_descriptors.py#L900-L905
The only documented pattern of accessing a field attribute] from the class
is for `ManyToMany.through` via `ManyToManyDescriptor.through` but there
might be valid use cases in the wild for expecting descriptors to be
returned that this change could break. As long as we document this change
and that it's still possible to retrieve descriptors by doing
`ModelClass.__dict__.get('descriptor')` I think we should be fine though.
Beyond the documentation benefits this could pave the way for interesting
features that the verbosity of `Model._meta.get_field` such as SQLAlchemy-
esque lookups (e.g.
`Book.objects.filter(Book.title.contains(Book.author.name))` ) but most
importantly it would restore the most intuitive pattern for field
retrieval.
--
Ticket URL: <https://code.djangoproject.com/ticket/12096#comment:11>