Вопрос по django, admin – Администратор Django - добавить пользовательские поля формы, которые не являются частью модели

77

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

Как я могу это сделать?

ОБНОВЛЕНИЕ: в основном то, что яя делаю построение математического или строкового выражения из символов, пользователь выбирает символы (это настраиваемые поля, которые не являются частью модели), и когда он нажимает кнопку «Сохранить», я создаю представление строкового выражения из списка символов и сохраняю его. в БД. Я неНе хочу, чтобы символы были частью модели, а БД - только конечным выражением.

Ваш Ответ

5   ответов
127

либо в отдельном файле forms.py вы можете добавить класс ModelForm, а затем объявить в нем свои дополнительные поля, как обычно. Я'Мы также привели пример того, как вы можете использовать эти значения в form.save ():

from django import forms
from yourapp.models import YourModel


class YourModelForm(forms.ModelForm):

    extra_field = forms.CharField()

    def save(self, commit=True):
        extra_field = self.cleaned_data.get('extra_field', None)
        # ...do something with extra_field here...
        return super(YourModelForm, self).save(commit=commit)

    class Meta:
        model = YourModel

Чтобы дополнительные поля появились в админке, просто:

отредактируйте ваш admin.py и установите свойство формы для ссылки на форму, которую вы создали вышевключить ваши новые поля в декларацию полей или наборов полей

Как это:

class YourModelAdmin(admin.ModelAdmin):

    form = YourModelForm

    fieldsets = (
        (None, {
            'fields': ('name', 'description', 'extra_field',),
        }),
    )

ОБНОВЛЕНИЕ: в django 1.8 нужно добавитьfields = '__all__' в метакласс YourModelForm.

Пожалуйста помоги! Это замечательно и работает почти идеально для моих нужд, но по какой-то причине, когда я нажимаю сохранить в админе, это на самом делесохраняет три раза. Итак, на линии: ~ # ... сделайте что-нибудь с extra_field здесь ... если я положу печать здесь, она печатает 3 раза .. (в моем случае это отправляет 3 электронных письма!) joeskru
@sthzg, потому что этоне правильно. Это дает мне ошибку:YourModelAdmin.list_display[0], 'extra_field' is not a callable or an attribute of 'YourModelAdmin' or found in the model 'YourModel'. Cerin
Да, я действительно хочу знать причину Vishnu
Есть ли причина, по которой этот ответ нет принято? sthzg
3

а не в двух отдельных полях, вы можете сделать что-то вроде этого:

Создайте пользовательскую форму, используяform атрибут на вашем (ModelAdminhttps://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form)Разбор пользовательских полей вsave_formset метод по вашему (ModelAdminhttps://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model)

Я никогда не делал что-то подобное, поэтому яЯ не совсем уверен, как это получится.

28

но не очень простой способ сделать это. Кроме того, я хотел бы посоветовать сохранить большую часть бизнес-логики в ваших моделях, чтобы вы выиграли.быть зависимым от администратора Django.

Возможно, будет проще (а может, даже лучше), если у вас есть два отдельных поля в вашей модели. Затем добавьте метод в вашу модель, который объединяет их.

Например:

class MyModel(models.model):

    field1 = models.CharField(max_length=10)
    field2 = models.CharField(max_length=10)

    def combined_fields(self):
        return '{} {}'.format(self.field1, self.field2)

Затем в админке вы можете добавитьcombined_fields() как поле только для чтения:

class MyModelAdmin(models.ModelAdmin):

    list_display = ('field1', 'field2', 'combined_fields')
    readonly_fields = ('combined_fields',)

    def combined_fields(self, obj):
        return obj.combined_fields()

Если вы хотите сохранитьcombined_fields в базе данных вы также можете сохранить ее при сохранении модели:

def save(self, *args, **kwargs):
    self.field3 = self.combined_fields()
    super(MyModel, self).save(*args, **kwargs)
еще раз спасибо, но проблема в том, что я нея не хочу хранить поля, которые объединяют последнее поле (то есть символы), я просто хочу сохранить последнюю строку michalv82
еще раз спасибо, но этоне 2 поля, вероятно, будет больше. Опять же, я не хочу хранить их в БД, поэтому это решение не может работать для меня. michalv82
Спасибо за ответ, но это не то, что яищу Я не хочу, чтобы пользовательские поля были сохранены в БД, только рассчитанная строка. В основном то, что яя делаю построение математического или строкового выражения из символов, пользователь выбирает символы (это настраиваемые поля, которые не являются частью модели), и когда он нажимает кнопку «Сохранить», я создаю представление строкового выражения из списка символов и сохраняю его. в БД. michalv82
Это проблема, чтобы сохранить 2 поля? Может быть, это пригодится, если вы хотите знать, как генерируется комбинированное поле. gitaarik
@ michalv82 Вы также можете сохранить его в базе данных в моделиsave() Метод, проверьте обновления моего ответа. gitaarik
4

что вам нужно, в вашем admin_view (переопределите добавление URL администратора к вашему admin_view):

 url(r'^admin/mymodel/mymodel/add/ , 'admin_views.add_my_special_model')
2

о не помогло мне сохранить результат в поле в моей реальной модели. В моем случае я хотел, чтобы текстовое поле, в которое пользователь мог вводить данные, затем при сохранении данные обрабатывались, а результат помещался в поле в модели и сохранялся. Хотя оригинальный ответ показал, как получить значение из дополнительного поля, он не показал, как сохранить его обратно в модель, по крайней мере, в Django 2.1.1.

Это берет значение из несвязанного настраиваемого поля, обрабатывает и сохраняет его в поле моего реального описания:

class WidgetForm(forms.ModelForm):
    extra_field = forms.CharField(required=False)

    def processData(self, input):
        # example of error handling
        if False:
            raise forms.ValidationError('Processing failed!')

        return input + " has been processed"

    def save(self, commit=True):
        extra_field = self.cleaned_data.get('extra_field', None)

        # self.description = "my result" note that this does not work

        # Get the form instance so I can write to its fields
        instance = super(WidgetForm, self).save(commit=commit)

        # this writes the processed data to the description field
        instance.description = self.processData(extra_field)

        if commit:
            instance.save()

        return instance

    class Meta:
        model = Widget
        fields = "__all__"

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