Skip to content

перевод документации пакета django-mptt 0.6.1 на русский

Notifications You must be signed in to change notification settings

baloon11/django-mptt_rus_translate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 

Repository files navigation

      Перевод документации django-mptt 0.6.1
    (Неполный, в процессе перевода и редактирования.)
  
http://django-mptt.github.io/django-mptt/overview.html

MPTT является методом хранения иерархических данных в базе данных.
Его цель состоит в том, чтобы сделать поисковые операции очень эффективными.
-----------------
ссылка "Хранение иерархических данных в БД" --http://www.sitepoint.com/hierarchical-data-database/
-----------------

    Обзор функций

     Простая регистрация моделей - поля, необходимые для древовидной структуры будут добавлены автоматически.
     
     Структура дерева автоматически обновляется при создании или удалении экземпляров модели, или измении родителя данных экземпляра.
     
     Каждый уровень дерева автоматически сортируются по полю (или полям) по вашему выбору.
  
     Новые методы модели добавляются к каждой зарегистрированной модели:
         изменение положения в дереве
         получение предков, братьев и сестер, потомков
         подсчет потомков
         другие операции  связанные с иерархическим деревом.
----------------------

Менеджер TreeManager добавляется для всех зарегистрированных моделей. 
    Этот менеджер предоставляет методы для:
 --   перемещения узлов внутри дерева или вынос узла в другое дерево,
 --   возможность вставить узел в любое место дерева,
 --   перестроить поля MPTT для дерева (полезно, когда вы делаете сыпучих 
      обновления за пределами   Django)
----------------------
 Также есть такие опции:
    Поля формы для моделей деревьев.
    Служебные функции для моделей деревьев.
    Шаблонные теги и фильтры для отображения деревьев.
     Переводы:
         датский
         французский
         немецкий
         польский
------------------------------------------------------------------
Tutorial -Учебник
http://django-mptt.github.io/django-mptt/tutorial.html

Задача
Вы создали проект Django, и вы должны управлять некоторыми иерархическими данными. 
Например, вы получили кучу иерархических страниц в CMS, а иногда и страниц,
которые являются потомками других страниц

Теперь предположим, что вы хотите показать "хлебные крошки" на вашем сайте,  например такие:
Home > Products > Food > Meat > Spam > Spammy McDelicious

Чтобы получить заголовки страниц вы должны были бы сделать что-то на подобии такого:
titles = []
while page:
    titles.append(page.title)
    page = page.parent

Это один запрос к базе данных для каждой страницы в навигационной цепочке, и запросы к базе данных будут происходить медленно. Давайте сделаем тоже самое лучшим образом.


Решение 
(MPTT-может показаться сложным на первый взгляд, но это лучшее решение, чтобы решать подобные задачи)

MPTT делает большинство операций с деревьями гораздо дешевле с точки зрения запросов. На самом деле все эти операции (представленные ниже)требуют не более одного запроса,а иногда требуется вообще ноль запросов:

        -- получить потомство узла
        --  получить предки узла
        -- получить все узлы на заданном уровне
        -- получить листовые узлы (leaf nodes)

А эта операция происходит вообще без дапроса:

        --  считать потомков данного узла
----------------------------------------------------
Давайте теперь разбираться

1. добавляем в INSTALLED_APPS: 
INSTALLED_APPS = (
    'django.contrib.auth',
    # ...
    'mptt',
)

2. Настроим нужную модель
Начните с модели-подкласса MPTTModel, что-то вроде этого:

from django.db import models
from mptt.models import MPTTModel, TreeForeignKey

class Genre(MPTTModel):
    name = models.CharField(max_length=50, unique=True)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

    class MPTTMeta:
        order_insertion_by = ['name']

Вы должны определить поле parent  как TreeForeignKey  и оно должно ссылаться на самого себя 'self'.

TreeForeignKey просто обычное ForeignKey,
которое отображает поля формы по-разному в админке и некоторых других местах.



Потому как мы наследовалить от MPTTModel, то
наша модель будет также иметь ряд других полей :
    level,
    lft, 
    rght, 
     и
    tree_id.
Эти поля управляются с помощью алгоритма MPTT.
Большую часть времени вам не нужно будет использовать эти поля непосредственно.

Класс MPTTMeta добавляет некоторые хитрости, 
в  django-mptt - в нашем случае, просто добавляет order_insertion_by. 
order_insertion_by указывает на естественный порядок сортировки данных в дереве.

3. Теперь создайте таблицу в БД.
   python manage.py syncdb

----------------------------------------
Теперь через  джанговский шелл можно создать несколько записей в таблицу:

python manage.py shell

Создаем несколько записей для проверки:

from myapp.models import Genre
rock = Genre.objects.create(name="Rock")
blues = Genre.objects.create(name="Blues")
Genre.objects.create(name="Hard Rock", parent=rock)
Genre.objects.create(name="Pop Rock", parent=rock)


Затем  Добавляем вот такое представление и url:

(Вы можете добавить это небольшое представление в views.py своего приложения)

def show_genres(request):
    return render_to_response("genres.html",
                          {'nodes':Genre.objects.all()}, 
                          context_instance=RequestContext(request))


Добавляем URL для этого представления в urls.py

(r'^genres/$', 'myapp.views.show_genres'),

----------------
http://django-mptt.github.io/django-mptt/tutorial.html#template
django-mptt предоставляет несколько тегов для простоты работы 

{% load mptt_tags %}  --подгрудаем теги 
<ul>
    {% recursetree nodes %}
        <li>
            {{ node.name }}
            {% if not node.is_leaf_node %} --если это не листовой узел (видимо, листовой - это уже без потомков)
                <ul class="children">
                    {{ children }}
                </ul>
            {% endif %}
        </li>
    {% endrecursetree %}
</ul>

---------------------------------------------------------------------------
 шаблонный тег recursetree  рекрусивно отображает этот фрагрент шаблона для всех узлов

Далее можете посмотреть документацию по тому

как кастомизировать админку,

разобраться с другими шаблонными тегами,

функциям перестройки дерева(tree rebuild functions) 
и т. д. 
----------------------------------------------------------------------------------------
 
 Документация  http://django-mptt.github.io/django-mptt/
Темы документации:

    Models and Managers(Модели и Менеджеры)
    Admin classes(классы в админке)
    Working with trees in Django forms (Работа с деревьями в django-формах)
    Working with trees in templates(Работа с деревьями в шаблонах)
    Utilities for working with trees (Утилиты для работы с деревьями)
    Upgrade notes (обновление примечаний)
    Technical details (технические детали)
-----------------------------------------------------------------------------------------
Models and Managers  http://django-mptt.github.io/django-mptt/models.html

        
        Настройка модели Django для MPTT (Setting up a Django model for MPTT) 

тут идет часть, где повторяется про модель (описанее как выше)
http://django-mptt.github.io/django-mptt/models.html#setting-up-a-django-model-for-mptt

далее:
если у вас модель наследуется от нескольких  ролителей, то MPTTModel должна  идти первой:
class Genre(MPTTModel,Foo,Bar):
    name = models.CharField(max_length=50, unique=True)

так происходит потому ,что MPTTModel наследуется от models.Model,
(и в моделях, соответственно, models.Model должен быть первым родителем)
-------------------------------------
           Опции моделей (Model Options)  
           http://django-mptt.github.io/django-mptt/models.html#model-options

Когда  мы переделываем модель под mptt, то добавляется несколько (4 шт) новых полей(см.выше и ниже).

Но может возникнуть ситуация, когда в изначальной модели уже есть поле с таким именем.
Может возникнуть конфликт
Чтобы его избежать, создайте MPTTMeta класс внутри класса модели:

class Genre(MPTTModel):
    name = models.CharField(max_length=50, unique=True)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

    class MPTTMeta:
        level_attr = 'mptt_level' # вот тут мы меняем имя поля, 
                                  # которое генерируется автоматически, чтобы избежать кофликта 

        order_insertion_by=['name']

 Доступны такие опции(атрибуты класса) для MPTTMeta:

 parent_attr

    The name of a field which relates the model back to itself 
    such that each instance can be a child of another instance. Defaults to 'parent'. 

Имя поля, которое является ForeignKey -- обратной связью на самого себя 
(каждый экземпляр может быть дочерним от другого экземпляра) По умолчанию 'parent'


Пользователи несут ответственность
за установку этого поля в классе модели, которая может быть выполнена следующим образом:
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

( То есть следует добавить это поле, при использовании django-mptt)
Если вы не хотите изменять структуру модели, то  есть возможность зарегистрировать модель в django-mptt,
 не меняя саму модель (см. ниже)
----------------------------------------------------

Для следующих четырех аргументов, 
если поля с заданными именами не существует, они будут добавлены к модели динамически:
(то есть у модели появятся  дополнительные поля)

(От преводчика. По умолчанию добавляются 4 доп поля --  если мы их прописываем сами, то это нужно указывать в
 MPTTMeta,  как в случае с 'parent', или, например,  если нужно задать им другое имя, во избежание конфликтов имен)

left_attr
Имя поля ,которое содержит  индикатор левого узла (иерархического дерева).
Это поле должно быть PositiveIntegerField. По умолчанию 'lft'.
('lft' назание атрибута модели)

--------------------
right_attr
Тоже самое что и left_attr, только это индикатор правого узла 
По умолчанию 'rght'.

--------------------
tree_id_attr
Имя поля, которое содержит  id-номер иерархического дерева  для каждого узла.
Должен быть PositiveIntegerField. По умолчанию 'tree_id'.

Экземпляры модели, у которых нет родителей, счиаются
“root”(корневыми) узлами (“root” nodes ) в иерархическом дереве.
Таким узлам будет выделено новое id (tree id).
То есть будет считаться что созданоновое дерево со своим id.
Всем потомкам корневых узлов будет дано то же самое tree id как и корневому узлу их дерева.

(От переводчика. То есть это tree id показывает, к какому дереву принадлежит узел.)
--------------------
level_attr
Имя поля, которое содержит (нулевой--zero-based) уровень,
на котором экземпляр находится на дереве.
Должно быть PositiveIntegerField.
По умолчанию 'level'.

Например, корневые узлы будут иметь  уровень(level) 0,
и их непосредственные дети имеют имеют уровень(level) 1.
--------------------
order_insertion_by (подкорректировать перевод)
 Список имен полей, которые должны определить порядок, 
 когда новые промежуточные узлы вставить или существующих узлов в настоящее время предок,
 с наиболее значительным заказа имени поля в первую очередь. По умолчанию [].
Предполагается, что любое поле о никогда не будет NULL в базе данных.(то есть всегда в ячейке что то есть)

Обратите внимание, что для этого потребуется дополнительный запрос к базе данных,
чтобы определить, где узлы должны быть расположены, когда они были сохранены.
Эта опция пригодится, если вы поддерживаете в основном статические структуры,
такие как деревья категорий, которые всегда должны быть в алфавитном порядке

----------------------------------------------------------------------------------------------------
 
            Регистрация существующих моделей (Registration of existing models)

Предпочтительный способ сделать регистрацию модели  в Django-mptt 0.4(тут видимо ошибка)
 является использование подкласса MPTTModel.

Однако, этот способ не всегда работает.

Предположим, вы хотите изменить джанго-модель Group --сделать ее иерархичной.
 Вы не можете использовать MPTTModel без модификации  исходного кода модели Group.
но вместо этого вы можете сделать так:

import mptt
from mptt.fields import TreeForeignKey
from django.contrib.auth.models import Group

# add a parent foreign key
TreeForeignKey(Group, blank=True, null=True).contribute_to_class(Group, 'parent')

mptt.register(Group, order_insertion_by=['name'])
----
то есть мы добавляем  внешним образом 
атрибут parent (который  обязательно необходим в каждой
иераархической модели модели для работы mptt)
----

mptt.register() был удален в 0.4.0  но восстановлен in 0.4.2 -- видимо, посчитали что нужен.
----------------------------------------------------------------------------------------------------
            
                Методы экземпляров модели MPTTModel (MPTTModel instance methods)
                http://django-mptt.github.io/django-mptt/models.html#mpttmodel-instance-methods

Экземпляры MPTTModel имеют нижеследующие  методы.

    get_ancestors(ascending=False, include_self=False)
    get_children()
    get_descendants(include_self=False)
    get_descendant_count()
    get_next_sibling()
    get_previous_sibling()
    get_root()
    get_siblings(include_self=False)
    insert_at(target, position='first-child', save=False)
    is_child_node()
    is_leaf_node()
    is_root_node()
    move_to(target, position='first-child')
-------------------------------
get_ancestors(ascending=False, include_self=False)

Создает QuerySet, содержащий список предков экземпляра модели.

По умолчанию список идет в порядке убывания (root -первый , непосредственный родитель--последний);

Если выставить ascending=True, то выдаст спискок, где непосредственный родитель--первый,root-последний. 

Если include_self=True, то в  QuerySet будет включен экземпляр модели,от которого вызывался этот метод.


------------------------------------------------
get_children ()

Создает QuerySet, содержащий непосредственных потомков экземпляра модели в этом  дереве.

Преимуществом использования данного метода , по сравнению с обычным использованием
обратной связи в стандартной django ORM  является то,
что в случае если узел не имеет детей (листовой узел - leaf node), то можно избежать запроса в БД.

------------------------------------------------
get_descendants (include_self = False)

Создает QuerySet, содержащий потомков экземпляра модели в этом дереве.

Если include_self=True, то в QuerySet будет включен экземпляр модели,от которого вызывался этот метод.

------------------------------------------------

get_descendant_count()

Возвращает число потомков экземпляра модели. 

Подсчет делается, на основе показаний left и right tree node edge индикаторов этого экземпляра. так что  этот метод не имеет 
никакого доступа у БД. 

(Returns the number of descendants the model instance has, 
based on its left and right tree node edge indicators.
As such, this does not incur any database access.)

------------------------------------------------
get_next_sibling()

Возвращает экземпляр модели, который является следующим братом данного экземпляра в иерархическом дереве. 
Если следующего брата нет, то возвращает None.

(От превовдчика, здесь, по видимому, имеется ввиду, что в иерархическом дереве могут быть экземпляры модели, которые находятся на одном уровне-- экземпляры-братья. То есть мы имеем дело со списком экземпляров- братьев,и соответственно может быть  как следующий в этом списке экземпляр, так и предыдущий, относительно экземпляра , от которого вызывался этот метод)

get_previous_sibling() -тоже самое что и в get_next_sibling(), но возвращает предыдущего в списке брата. 

------------------------------------------------
get_root()

Returns the root node of the model instance’s tree.
Возвращает  экземпляр модели--корневой узел
------------------------------------------------

get_siblings(include_self=False)

Создает QuerySet, содержащий братьев и сестер экземпляра модели. 

Для рут узлов братьями считаются другие рут узлы. 

Если include_self=True, то в  QuerySet будет включен экземпляр модели, от которого был вызван этот метод.
------------------------------------------------

insert_at(target, position='first-child', save=False)

Позиционирование экземпляра модели 
(при условии что этот экземпляр еще не был сохранен в БД)
в иерархическом дереве на основе передаваемых аргументов target 
(от переводчика,target,экземпляр,который будет являтся родительским после позиционирования)
и  position (при необходимости).

Можно также указать save=True, в этом случае будет также вызван метод  save() этой модели.
------------------------------------------------

is_child_node()
Возвращает True, если данный экземпляр-дочерний узел(child node),в обратном случае -вернет False.

------------------------------------------------

is_leaf_node()
Возвращает True, если данный экземпляр-листовой узел(leaf node -узел без наследников),в обратном случае -вернет False.

------------------------------------------------

is_root_node()
Returns True if the model instance is a root node, False otherwise
Возвращает True, если данный экземпляр-корневой узел(root node),в обратном случае -вернет False.

------------------------------------------------

move_to(target, position='first-child')
Перемещение экземпляра модели в иерархическом дереве, 
основываясь на аргументах target и position(при необходимости)
--------

Примечание 
Предполагается, что когда вы вызываете этот метод,
поля экземпляра, которые отвечают за древовидную стркутуру в экземпляре(древ. поля), к которому был применен этот метод , и  экземпляр, к которому мы будем привязывать  пермещаемый экземпляр,
все они отражают  текущее состояние базы данных.

Модификация  полей, которые отвечают за древовидную стркутуру,вручную  перед вызовом этого метода или использование древ. полей, которые не синхронизированы с БД, может привести к перемещению нужного экземпляра не в то место, куда предполагалось. 
--------
Если target  это  другой экземпляр модели, то  он будет использоваться для определения типа перемещения, которое необходимо провести, и будет использоваться в качестве основы для позиционирования модели, когда он перемещается в сочетании с аргументом position .

Если target  является None - это указывает на то, что экземпляр модели должен быть включен в корневой узел.
Аргумент position( положение) не учитывается в данном случае.

-----------------------------

Допустимые значения для аргумента position и их эффект на перемещение:
'first-child'
    Экземпляр в качестве своего нового родительского узла принимает target. Встраивается в качестве его первого дочернего узла (first child) в древовидной структуре


'last-child'
    Экземпляр в качестве своего нового родительского узла принимает target. Встраивается в качестве его последнего дочернего узла (last-child) в древовидной структуре


'left'
    The instance being moved should have target‘s parent set as its new parent and should be placed directly before target in the tree structure.

Экземпляр , который перемещается, в качестве родителя будет воспринимать  список узлов, в котором находится узел target, В списке он встроится непосредственно перед узлом target.(от переводчика, скорее всего имелось ввиду, что родителем будет родительский узел всего этого списка, и переносимый экземпляр просто  встроится в этот список до target )


'right'
 тоже самое что и 'left' но только  встраивается после target.
-----------
Если мы передадим неправильное значение  аргументу position, то вызовится исключение ValueError

Обратите внимание, что некоторые из шагов, которые
Вы могли бы попытаться сделать с помощью этого метода являются недопустимыми.

Например,  допустим,  у нас есть объект , его дочерний и внучатый объект,
Невозможно  перенести объект и сделать
его дочерним относительно его же дочернего или внучатого объекта.
В этом случае  будет возбуждено исключение mptt.exceptions.InvalidMove


Сам экземпляр притерпевает изменения, так что наиболее правильным 
будет сохранить обновление в БД после вызова этого метода.
----------------------------------------------------------------------------------------------
TreeForeignKey, TreeOneToOneField, TreeManyToManyField 
http://django-mptt.github.io/django-mptt/models.html#treeforeignkey-treeonetoonefield-treemanytomanyfield
New in version 0.5.

 New in version 0.5.

It’s recommended you use mptt.fields.TreeForeignKey wherever you have a foreign key to an MPTT model. This includes the parent link you’ve just created on your model.

TreeForeignKey is just like a regular ForeignKey but it makes the default form field display choices in tree form.

There are also TreeOneToOneField and TreeManyToManyField if you need them. These may come in useful on other models that relate to your tree model in some way.

Если вы хотите иметь в своей модели внешний ключ и использовать django-mptt, 
то воспользуйтесь mptt.fields.TreeForeignKey
он включает в себя ссылку на родителя.

TreeForeignKey подобен обычному ForeignKey, он делает по умолчанию отображение полей форм выбора
в виде древовидной структуры( конечно, там где это нужно)

Также есть TreeOneToOneField и  TreeManyToManyField поля.
Они могут пригодиться в других моделях, которые ссылаются на вашу древовидную модель.

--------------------------------------------------------   










About

перевод документации пакета django-mptt 0.6.1 на русский

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published