Подтвердить что ты не робот

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

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

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

UPDATE: В основном то, что я делаю, это построение математического или строкового выражения из символов, пользователь выбирает символы (это настраиваемые поля, которые не являются частью модели), и когда он нажимает на сохранение, я создаю представление строкового выражения из списка символов и сохранить их в БД. Я не хочу, чтобы символы были частью модели и DB, а только окончательное выражение.

4b9b3361

Ответ 1

Либо в файле admin.py, либо в отдельном файле 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

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

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

Как это:

class YourModelAdmin(admin.ModelAdmin):

    form = YourModelForm

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

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

Ответ 2

Это возможно сделать в админе, но нет очень простого пути к нему. Кроме того, я хотел бы посоветовать сохранить большинство бизнес-логики в ваших моделях, поэтому вы не будете зависеть от администратора 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)

Затем в admin вы можете добавить 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)

Ответ 3

вы всегда можете создать новый шаблон администратора и сделать то, что вам нужно в вашем admin_view (переопределить админ, добавляющий url для вашего admin_view):

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

Ответ 4

Если вы абсолютно хотите хранить комбинированное поле на модели, а не два отдельных поля, вы можете сделать что-то вроде этого:

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

Ответ 5

Джанго 2.1.1. Первичный ответ дал мне половину ответа на мой вопрос. Это не помогло мне сохранить результат в поле в моей реальной модели. В моем случае я хотел, чтобы текстовое поле, в которое пользователь мог вводить данные, затем, когда происходило сохранение, данные обрабатывались, а результат помещался в поле в модели и сохранялся. Хотя оригинальный ответ показал, как получить значение из дополнительного поля, он не показал, как сохранить его обратно в модель, по крайней мере, в 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__"

Ответ 6

Сначала добавьте поле в форму

class CreateForm(forms.ModelForm):

extra_field     = forms.CharField(label = 'extra_field', required = False)

Теперь при очистке данных вам нужно извлечь дополнительное поле из self.data, а не self.cleaned_data.

Исправить:

 self.data.get('extra_field')

Неправильно

 self.cleaned_data.get('extra_field')