Как я получаю доступ к дочерним классам объекта в django, не зная название дочернего класса?

Чтобы передать пароль в стандартный ввод sudo:

#!/usr/bin/env python
from subprocess import Popen, PIPE

sudo_password = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'.split()

p = Popen(['sudo', '-S'] + command, stdin=PIPE, stderr=PIPE,
          universal_newlines=True)
sudo_prompt = p.communicate(sudo_password + '\n')[1]

Примечание: вы, вероятно, могли бы сконфигурировать команду sudo или SUDO_ASKPASS без пароля вместо жесткого ввода пароля в исходном коде.

78
задан Gabriel Hurley 30 May 2009 в 04:52
поделиться

5 ответов

( Обновление : для Django 1.2 и новее, которые могут следовать запросам select_related через обратные отношения OneToOneField (и, таким образом, вниз по иерархиям наследования), доступен лучший метод, который не Для этого требуется добавленное поле real_type в родительской модели. Оно доступно как InheritanceManager в проекте django-model-utils .)

Обычный способ Сделайте это, чтобы добавить ForeignKey в ContentType в модели Parent, которая хранит тип контента соответствующего «листового» класса. Без этого вам может потребоваться выполнить большое количество запросов к дочерним таблицам, чтобы найти экземпляр, в зависимости от размера вашего дерева наследования. Вот как я сделал это в одном проекте:

from django.contrib.contenttypes.models import ContentType
from django.db import models

class InheritanceCastModel(models.Model):
    """
    An abstract base class that provides a ``real_type`` FK to ContentType.

    For use in trees of inherited models, to be able to downcast
    parent instances to their child types.

    """
    real_type = models.ForeignKey(ContentType, editable=False)

    def save(self, *args, **kwargs):
        if not self._state.adding:
            self.real_type = self._get_real_type()
        super(InheritanceCastModel, self).save(*args, **kwargs)

    def _get_real_type(self):
        return ContentType.objects.get_for_model(type(self))

    def cast(self):
        return self.real_type.get_object_for_this_type(pk=self.pk)

    class Meta:
        abstract = True

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

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

81
ответ дан 24 November 2019 в 10:38
поделиться

Решение Карла хорошее, вот один из способов сделать это вручную, если есть несколько связанных дочерних классов:

def get_children(self):
    rel_objs = self._meta.get_all_related_objects()
    return [getattr(self, x.get_accessor_name()) for x in rel_objs if x.model != type(self)]

Он использует функцию из _meta, стабильность которой не гарантируется. по мере развития django, но он помогает и при необходимости может использоваться "на лету".

5
ответ дан 24 November 2019 в 10:38
поделиться

В Python при заданном (" новый стиль ") класса X, вы можете получить его (прямые) подклассы с помощью X .__ subclasses __ () , который возвращает список объектов класса. (Если вам нужны «дальнейшие потомки», вам также нужно будет вызвать __ подклассов __ для каждого из прямых подклассов и т. Д. И т. Д. И т. Д. - если вам нужна помощь в том, как это сделать эффективно в Python, просто спросите! ).

После того, как вы каким-то образом определили интересующий дочерний класс (может быть, все они, если вам нужны экземпляры всех дочерних подклассов и т. Д.), getattr (parentclass, '% s_set'% childclass .__ name __) должен помочь (если имя дочернего класса 'foo' , это похоже на доступ к parentclass.foo_set - ни больше, ни меньше). Опять же, если вам нужны пояснения или примеры, спрашивайте!

и т. д. и т. д. - если вам нужна помощь в том, как сделать это эффективно в Python, просто спросите!).

После того, как вы каким-то образом определили интересующий дочерний класс (возможно, все они, если вам нужны экземпляры всех дочерних подклассов, и т.д.), getattr (parentclass, '% s_set'% childclass .__ name __) должен помочь (если имя дочернего класса 'foo' , это похоже на доступ к родительскому классу .foo_set - ни больше, ни меньше). Опять же, если вам нужны пояснения или примеры, спрашивайте!

и т. д. и т. д. - если вам нужна помощь в том, как сделать это эффективно в Python, просто спросите!).

После того, как вы каким-то образом определили интересующий дочерний класс (возможно, все они, если вам нужны экземпляры всех дочерних подклассов, и т.д.), getattr (parentclass, '% s_set'% childclass .__ name __) должен помочь (если имя дочернего класса 'foo' , это похоже на доступ к родительскому классу .foo_set - ни больше, ни меньше). Опять же, если вам нужны пояснения или примеры, спрашивайте!

это похоже на доступ к parentclass.foo_set - ни больше ни меньше). Опять же, если вам нужны пояснения или примеры, спрашивайте!

это похоже на доступ к parentclass.foo_set - ни больше ни меньше). Опять же, если вам нужны пояснения или примеры, спрашивайте!

21
ответ дан 24 November 2019 в 10:38
поделиться

Вы можете добиться этого, ища все поля в родительском элементе, которые являются экземпляром django.db.models.fields.related.RelatedManager. Из вашего примера кажется, что дочерние классы, о которых вы говорите, не являются подклассами. Верно?

0
ответ дан 24 November 2019 в 10:38
поделиться

Оказалось, что мне действительно нужно было следующее:

Наследование модели с типом контента и менеджером, учитывающим наследование

Это отлично сработало для меня. Но спасибо всем остальным. Я многому научился, просто читая ваши ответы!

5
ответ дан 24 November 2019 в 10:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: