Django - получает экземпляр pk внутри класса виджета - PullRequest
3 голосов
/ 30 марта 2011

Я создал собственный виджет, который имеет ссылку на некоторые функции AJAX. Чтобы заставить это работать, мне нужно передать pk экземпляра, который я сейчас редактирую. Кажется, что виджеты не имеют доступа к текущему экземпляру модели (по уважительной причине!), Поэтому мне было интересно, как я могу получить эту информацию? Должен ли я получить его из URI или есть удобный метод, который я пропускаю, который даст мне то, что мне нужно.

Спасибо

Ответы [ 3 ]

5 голосов
/ 31 марта 2011

Вы можете переопределить метод __init__ виджета и передать ему экземпляр формы. Из экземпляра формы вы можете получить pk, если он существует.

В этом ответе они связывают form_instance с виджетом в init формы.

django - как получить доступ к полю формы из пользовательского виджета

Вот еще одна статья с вопросом о пользовательских виджетах, обращающихся к экземплярам форм.

Раскрывающиеся меню "Страна / Штат / Город" в строке администратора Django

1 голос
/ 16 октября 2017

В дополнение к выбранному ответу: чтобы использовать AdvancedModelChoiceField и по-прежнему отображать форму с помощью обычных виджетов, я переклассифицировал виджет django и переопределил некоторые методы.Первый метод будет Optgroups.Замените

for index, (option_value, option_label) in enumerate(chain(self.choices)):

на

for index, (option_value, option_label, obj) in enumerate(chain(self.choices)):

Затем нам нужно передать этот объект в параметр.

def create_option(self, name, value, label, selected, index, subindex=None, attrs=None, obj=None):
    option = super(RadioSelect, self).create_option(name, value, label, selected, index, subindex, attrs)
    option['obj'] = obj
    return option

В шаблоне виджета доступ к объекту выглядит следующим образом:

{{ widget.obj.object_attr }}

И, наконец, мы можем использовать наш собственный виджет и поле в нашей форме:

class MyForm(forms.ModelForm):
myfield = AdvancedModelChoiceField(
    widget=MyWidget,
    queryset=MyModel.objects.all(),
    empty_label=None
)
0 голосов
/ 09 ноября 2016

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

Например, я переопределяю класс ForeignKey, чтобы добавить ссылку после ввода select.

Виджет:

class SelectAdd(widgets.Select):
    def __init__(self, related_name, related_create_url, attrs=None):
        self.related_name = related_name
        self.related_create_url = related_create_url
        super().__init__(attrs=attrs)

    def render(self, name, value, attrs=None, **kwargs):
        rendered = super(SelectAdd, self).render(name, value, attrs, **kwargs)
        return rendered + mark_safe(u'''
           <span>Add new {} : {}</span>
           '''.format(self.related_name, self.related_create_url))

И поле модели:

class ForeignKeyAdd(ForeignKey):
    def formfield(self, **kwargs):
        db = kwargs.pop('using', None)
        if isinstance(self.remote_field.model, six.string_types):
            raise ValueError("Cannot create form field for %r yet, because "
                             "its related model %r has not been loaded yet" %
                             (self.name, self.remote_field.model))
        defaults = {
            'form_class': forms.ModelChoiceField,
            'queryset': self.remote_field.model._default_manager.using(db),
            'to_field_name': self.remote_field.field_name,
            'widget': SelectAdd(
                related_name=self.name,
                related_create_url=get_crud_url(self.related_model, 'create')
            ),
        }
        defaults.update(kwargs)
        return super(ForeignKey, self).formfield(**defaults)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...