Merge remote-tracking branch 'upstream/master' into permissions

This commit is contained in:
Rivo Laks 2013-05-18 16:58:51 +02:00
commit 779c0f3d25
14 changed files with 373 additions and 68 deletions

11
.travis.yml Normal file
View file

@ -0,0 +1,11 @@
language: python
python:
- "2.6"
- "2.7"
before_install:
- export PIP_USE_MIRRORS=true
- export PIP_INDEX_URL=https://simple.crate.io/
install:
- python setup.py develop
script:
- python runtests.py

View file

@ -13,3 +13,5 @@ Developers
* Ludvig Wadenstein (@ludw)
* Raphael Kimmig (@RaphaelKimmig)
* Andrew Ingram (@AndrewIngram)
* Gregor Müllegger (@gregmuellegger)

View file

@ -2,6 +2,10 @@
django-admin2
===============
.. image:: https://travis-ci.org/pydanny/django-admin2.png
:alt: Build Status
:target: https://travis-ci.org/pydanny/django-admin2
One of the most useful parts of ``django.contrib.admin`` is the ability to configure various views that touch and alter data. django-admin2 is a complete rewrite of that library using modern Class-Based Views and enjoying a design focused on extendibility. By starting over, we can avoid the legacy code and make it easier to write extensions and themes.
**Note:** This is pre-alpha and currently non-functional. We'll try and have a rough working prototype by the end of May 18th, 2013.

View file

@ -1,4 +1,4 @@
{% extends "admin/base.html" %}
{% extends "admin2/bootstrap/base.html" %}
{% block content %}

View file

@ -1,4 +1,4 @@
{% extends "admin/base.html" %}
{% extends "admin2/bootstrap/base.html" %}
{% block content %}

View file

@ -1,4 +1,4 @@
{% extends "admin/base.html" %}
{% extends "admin2/bootstrap/base.html" %}
{% block content %}

View file

@ -1,4 +1,4 @@
{% extends "admin/base.html" %}
{% extends "admin2/bootstrap/base.html" %}
{% block content %}

View file

@ -1,4 +1,4 @@
{% extends "admin/base.html" %}
{% extends "admin2/bootstrap/base.html" %}
{% block content %}
<a href="./create/">add</a>

View file

@ -1,10 +1,9 @@
from os.path import join
import os
from django.conf import settings
from django.forms.models import modelform_factory
from django.db import models
from django.views import generic
from django.db import models
from braces.views import LoginRequiredMixin, StaffuserRequiredMixin
@ -12,77 +11,49 @@ from .utils import get_admin2s
ADMIN2_THEME_DIRECTORY = getattr(settings, "ADMIN2_THEME_DIRECTORY", "admin2/bootstrap")
class IndexView(generic.ListView): #(LoginRequiredMixin, StaffuserRequiredMixin, ListView):
class Admin2Mixin(object):
def get_template_names(self):
return [join(ADMIN2_THEME_DIRECTORY, "index.html")]
return [os.path.join(ADMIN2_THEME_DIRECTORY, self.default_template_name)]
def get_model(self):
return self.model
def get_queryset(self):
return self.get_model()._default_manager.all()
def get_form_class(self):
if self.form_class is not None:
return self.form_class
return modelform_factory(self.get_model())
class IndexView(Admin2Mixin, generic.ListView):
default_template_name = "index.html"
def get_queryset(self):
return get_admin2s()
class ModelListView(generic.ListView):
def get_template_names(self):
return [join(ADMIN2_THEME_DIRECTORY, "model_list.html")]
def get_model(self):
return self.model
def get_queryset(self):
return self.get_model()._default_manager.all()
class ModelListView(Admin2Mixin, generic.ListView):
default_template_name = "model_list.html"
class ModelDetailView(generic.DetailView):
def get_template_names(self):
return [join(ADMIN2_THEME_DIRECTORY, "model_detail.html")]
def get_model(self):
return self.model
def get_queryset(self):
return self.get_model()._default_manager.all()
class ModelDetailView(Admin2Mixin, generic.DetailView):
default_template_name = "model_detail.html"
class ModelEditFormView(generic.UpdateView):
class ModelEditFormView(Admin2Mixin, generic.UpdateView):
form_class = None
success_url = "../../"
default_template_name = "model_edit_form.html"
def get_template_names(self):
return [join(ADMIN2_THEME_DIRECTORY, "model_edit_form.html")]
def get_model(self):
return self.model
def get_queryset(self):
return self.get_model()._default_manager.all()
class ModelAddFormView(generic.CreateView):
class ModelAddFormView(Admin2Mixin, generic.CreateView):
form_class = None
success_url = "../"
def get_template_names(self):
return [join(ADMIN2_THEME_DIRECTORY, "model_add_form.html")]
def get_model(self):
return self.model
def get_queryset(self):
return self.get_model()._default_manager.all()
default_template_name = "model_add_form.html"
class ModelDeleteView(generic.DeleteView):
class ModelDeleteView(Admin2Mixin, generic.DeleteView):
success_url = "../../"
def get_template_names(self):
return [join(ADMIN2_THEME_DIRECTORY, "model_delete_form.html")]
def get_model(self):
return self.model
def get_queryset(self):
return self.get_model()._default_manager.all()
default_template_name = "model_delete.html"

17
docs/README Normal file
View file

@ -0,0 +1,17 @@
The documentation in this tree is in plain text files and can be viewed using
any text file viewer.
It uses ReST (reStructuredText) [1], and the Sphinx documentation system [2].
This allows it to be built into other forms for easier viewing and browsing.
To create an HTML version of the docs:
* Install Sphinx (using ``sudo pip install Sphinx`` or some other method)
* In this docs/ directory, type ``make html`` (or ``make.bat html`` on
Windows) at a shell prompt.
The documentation in _build/html/index.html can then be viewed in a web browser.
[1] http://docutils.sourceforge.net/rst.html
[2] http://sphinx.pocoo.org/

View file

@ -249,4 +249,8 @@ texinfo_documents = [
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
intersphinx_mapping = {
'django': (
'http://docs.djangoproject.com/en/dev/',
'http://docs.djangoproject.com/en/dev/_objects/'),
}

View file

@ -35,6 +35,7 @@ Content
contributing
design
meta
Indices and tables
==================

288
docs/meta.rst Normal file
View file

@ -0,0 +1,288 @@
====================
Django's Model._meta
====================
Currently django implements most of its behaviour that makes using models so
nice using a metaclass. A metaclass is invoked when an actual class is created
and can change that class' behaviour by adding or modifing its attributes and
methods. This means that django is actually changing your model class at the
moment when the ``models.py`` file of your app is loaded.
One of those changes is that the model's metaclass takes the specified
``Meta`` options that the model has attached to and uses it's attributes in
conjunction with the model's fields to create a new attribute on the model
that is called ``_meta``. This is then responsible for providing an API to
access all database related information like the name of the database table or
a list of all available fields.
Django doesn't currently have an official documentation of the ``_meta``'s
semantics, however it is kind of a stable API since many projects and all the
db related django internals depend on it. And this page is about documenting
the semantics of ``_meta``.
Trivia
======
The ``Model._meta`` attribute is an instance of the
``django.db.models.options.Options`` class. It gets attached to the model at
that time when the model class is created by the
``django.db.models.base.ModelBase`` metaclass.
If ``_meta`` is mentioned we speak about the autogenerated ``_meta``
attribute that is attached to the model class.
Some clarifying: In the following text ``Meta`` is referring to the actual
``class Meta:`` definition that the app author has put inside the model class.
Like here::
class Restaurant(models.Model):
# ... some fields here ...
class Meta:
ordering = ('name',)
Attributes copied from ``Meta``
===============================
.. the django intersphinx link doesn't work :-(
Some of ``_meta``'s attributes are just copied from the ``Meta`` options. The
following attributes are those. Their behaviour is more detailed described in
the :doc:`django documentation <django:/ref/models/options>`.
``abstract``
A boolean value.
See the django documentation on :attr:`~django.db.models.Options.abstract`
for more information.
``app_label``
By default it is the name of the app module that the model was created in.
This can be overriden in ``Meta`` to make a model part of a specific
app.
Also see the django documentation about
:attr:`~django.db.models.Options.app_label`.
``db_table``
Contains the name of the database table used for this model. This is
either what was set on ``Meta`` or defaults to a string that is built
from ``app_label`` and ``model_name`` seperated by an underscore. So for
example the ``db_table`` for ``django.contrib.auth.models.User`` is
``'auth_user'``.
Also see the django documentation about
:attr:`~django.db.models.Options.db_table`.
``db_tablespace``
See the django documentation on
:attr:`~django.db.models.Options.db_tablespace` for more information.
``get_latest_by``
The name of the field that should be used during ordering to make
:meth:`~django.db.models.query.QuerySet.latest` and
:meth:`~django.db.models.query.QuerySet.earliest` work.
Also see the django documentation about
:attr:`~django.db.models.Options.get_latest_by`.
``managed``
If ``managed`` is ``True`` then the :djadmin:`syncdb` management command will take care of creating the database tables. Defaults to ``True``.
Also see the django documentation about
:attr:`~django.db.models.Options.managed`.
``order_with_respect_to``
See the django documentation on
:attr:`~django.db.models.Options.order_with_respect_to` for more information.
``ordering``
See the django documentation on
:attr:`~django.db.models.Options.ordering` for more information.
``permissions``
See the django documentation on
:attr:`~django.db.models.Options.permissions` for more information.
``proxy``
If set to ``True`` then this model will be treated a :ref:`proxy model
<proxy-models>`.
Also see the django documentation about
:attr:`~django.db.models.Options.proxy`.
``index_together``
See the django documentation on
:attr:`~django.db.models.Options.index_together` for more information.
``unique_together``
See the django documentation on
:attr:`~django.db.models.Options.unique_together` for more information.
``verbose_name``
A human-readable name of the models name, singular. If this is not set in
``Meta``, django will try to guess a human readable name by using the
``object_name`` and inserting appropriate spaces for the CamelCased model
name and then making everything lowercase.
See the django documentation on
:attr:`~django.db.models.Options.verbose_name` for more information.
``verbose_name_plural``
A human-readable name of the models name, plural. If this is not set in
``Meta``, it will default to ``verbose_name`` + ``"s"``.
See the django documentation on
:attr:`~django.db.models.Options.verbose_name_plural` for more information.
Attributes
==========
``abstract_managers``
To handle various inheritance situations, we need to track where
managers came from (concrete or abstract base classes).
..
``admin``
Is ``None``. Doesn't seem to be used anywhere. So we don't need to
document it.
TODO: Create a django ticket to suggest removing it.
``auto_created``
TODO ...
``auto_field``
TODO ...
``concrete_managers``
TODO ...
``concrete_model``
TODO ...
``has_auto_field``
TODO ...
``local_fields``
TODO ...
``local_many_to_many``
TODO ...
``model``
This is the actual ``django.db.models.Model`` that the ``_meta`` attribute
is attached to.
``model_name``
TODO ...
``object_name``
It is the actual name of the model class.
``parents``
TODO ...
``pk``
TODO ...
``proxy_for_model``
For any class that is a proxy (including automatically created
classes for deferred object loading), ``proxy_for_model`` tells us
which class this model is proxying. Note that ``proxy_for_model``
can create a chain of proxy models. For non-proxy models, the
variable is always ``None``.
``related_fkey_lookups``
List of all lookups defined in ForeignKey 'limit_choices_to' options
from *other* models. Needed for some admin checks. Internal use only.
``swappable``
TODO ...
``virtual_fields``
TODO ...
Methods
=======
``module_name(self)``
TODO ...
``add_field(self, field)``
TODO ...
``add_virtual_field(self, field)``
TODO ...
``setup_pk(self, field)``
TODO ...
``pk_index(self)``
TODO ...
``setup_proxy(self, target)``
TODO ...
``verbose_name_raw(self)``
TODO ...
``fields(self)``
TODO ...
``concrete_fields(self)``
TODO ...
``local_concrete_fields(self)``
TODO ...
``get_fields_with_model(self)``
TODO ...
``get_concrete_fields_with_model(self)``
TODO ...
``get_m2m_with_model(self)``
TODO ...
``get_field(self, name, many_to_many=True)``
TODO ...
``get_field_by_name(self, name)``
TODO ...
``get_all_field_names(self)``
TODO ...
``init_name_map(self)``
TODO ...
``get_add_permission(self)``
TODO ...
``get_change_permission(self)``
TODO ...
``get_delete_permission(self)``
TODO ...
``get_all_related_objects(self, local_only=False, include_hidden=False``
TODO ...
``get_all_related_objects_with_model(self, local_only=False``
TODO ...
``get_all_related_many_to_many_objects(self, local_only=False)``
TODO ...
``get_all_related_m2m_objects_with_model(self)``
TODO ...
``get_base_chain(self, model)``
TODO ...
``get_parent_list(self)``
TODO ...
``get_ancestor_link(self, ancestor)``
TODO ...

View file

@ -7,12 +7,20 @@ import os
import sys
def get_author(package):
"""
Return package version as listed in `__version__` in `init.py`.
"""
init_py = open(os.path.join(package, '__init__.py')).read()
return re.search("__author__ = ['\"]([^'\"]+)['\"]", init_py).group(1)
def get_version(package):
"""
Return package version as listed in `__version__` in `init.py`.
"""
init_py = open(os.path.join(package, '__init__.py')).read()
return re.match("__version__ = ['\"]([^'\"]+)['\"]", init_py).group(1)
return re.search("__version__ = ['\"]([^'\"]+)['\"]", init_py).group(1)
def get_packages(package):
@ -40,6 +48,7 @@ def get_package_data(package):
return {package: filepaths}
author = get_author('djadmin2')
version = get_version('djadmin2')
@ -50,8 +59,6 @@ if sys.argv[-1] == 'publish':
print(" git push --tags")
sys.exit()
import djadmin2
LONG_DESCRIPTION = open('README.rst').read()
setup(
@ -73,7 +80,7 @@ setup(
"Topic :: Software Development :: Libraries :: Python Modules",
],
keywords='django,admin',
author=djadmin2.__author__,
author=author,
author_email='pydanny@gmail.com',
url='http://github.com/pydanny/django-admin2',
license='MIT',