django admin - modelin parçası olmayan özel form alanları ekleyin


108

Yönetici sitesinde kayıtlı bir modelim var. Alanlarından biri uzun bir dizgi ifadesidir. Yönetici içerisindeki bu modelin ekle / güncelle sayfasına özel form alanları eklemek istiyorum, bu alan değerlerine göre uzun string ifadesini oluşturup ilgili model alanına kaydedeceğim.

Bunu nasıl yapabilirim?

GÜNCELLEME: Temel olarak yaptığım şey, sembollerden bir matematiksel veya dize ifadesi oluşturmaktır, kullanıcı sembolleri seçer (bunlar, modelin parçası olmayan özel alanlardır) ve kaydet'i tıkladığında, semboller listesi ve DB'de saklayın. Sembollerin modelin ve DB'nin bir parçası olmasını istemiyorum, sadece son ifade.

Yanıtlar:


156

Ya admin.py içinde ya da ayrı bir forms.py içinde bir ModelForm sınıfı ekleyebilir ve ardından normalde yaptığınız gibi bu sınıfın içindeki ekstra alanlarınızı bildirebilirsiniz. Ayrıca form.save () içinde bu değerleri nasıl kullanabileceğinize dair bir örnek verdim:

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

Ekstra alanların yöneticide görünmesini sağlamak için sadece:

  1. admin.py dosyanızı düzenleyin ve form özelliğini yukarıda oluşturduğunuz forma başvuracak şekilde ayarlayın
  2. yeni alanlarınızı alanlarınıza veya alan kümelerinize dahil edin

Bunun gibi:

class YourModelAdmin(admin.ModelAdmin):

    form = YourModelForm

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

GÜNCELLEME: django 1.8'de fields = '__all__'YourModelForm'un meta sınıfına eklemeniz gerekir .


2
Evet, sebebini gerçekten bilmek istiyorum
Vishnu 05

14
Sen eklemek gerekir fields = '__all__'senin içinde Metaaksi Django şikayet, sınıf:Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is deprecated
isaackleiner

1
@sthzg, Çünkü doğru değil. Bana şu hatayı veriyor:YourModelAdmin.list_display[0], 'extra_field' is not a callable or an attribute of 'YourModelAdmin' or found in the model 'YourModel'.
Cerin

7
Herhangi bir nedenle bir alırsanız , tanıma AttributeError: Unable to lookup "extra_field"...a eklemeyi deneyin . Görünüşe göre django, bu tür bir öznitelik tanımına ve bu tür bir öznitelik tanımına bakarak etiketini "tahmin etmeye" çalışıyor . labelextra_fieldModelModelAdmin
alxs

1
Extra_field bir CharField () ise bu çok güzel çalıştı. Bir hiddenField ise [Django 1.11'de], bir hata üretilir Unknown field(s) (extra_field) specified for YourModel. Check fields/fieldsets/exclude attributes of class YourModelAdmin.. Bunun için geçici çözümextra_field = forms.CharField(widget=forms.HiddenInput())
kakoma

36

Yöneticide yapmak mümkündür, ancak bunun çok basit bir yolu yoktur. Ayrıca, çoğu iş mantığını modellerinizde tutmanızı tavsiye ederim, böylece Django Yöneticisine bağımlı kalmayacaksınız.

Modelinizde iki ayrı alan varsa, belki daha kolay (ve belki daha da iyi) olurdu. Ardından modelinize bunları birleştiren bir yöntem ekleyin.

Örneğin:

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)

Ardından, yöneticide, combined_fields()salt okunur alanı olarak ekleyebilirsiniz :

class MyModelAdmin(models.ModelAdmin):

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

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

combined_fieldsVeritabanında saklamak istiyorsanız, modeli kaydettiğinizde de kaydedebilirsiniz:

def save(self, *args, **kwargs):
    self.field3 = self.combined_fields()
    super(MyModel, self).save(*args, **kwargs)

4
Cevap için teşekkürler, ama aradığım bu değil. Özel alanların DB'ye kaydedilmesini istemiyorum, sadece hesaplanan dizenin. Temel olarak yaptığım şey, sembollerden matematiksel veya dize ifadesi oluşturmaktır, kullanıcı sembolleri seçer (bunlar modelin parçası olmayan özel alanlardır) ve kaydet'i tıkladığında, listeden bir dize ifadesi gösterimi oluşturuyorum. sembollerini girin ve DB'de saklayın.
michalv82

@ michalv82 Model save()metodundaki veritabanına da kaydedebilirsiniz , cevabımın güncellemelerini kontrol edin.
gitaarik

1
tekrar teşekkürler, ancak sorun şu ki, son alanı (yani sembolleri) birleştiren alanları saklamak istemiyorum, sadece son dizenin kaydedilmesini istiyorum
michalv82

2 alanı kaydetmek sorun olur mu? Birleştirilmiş alanın nasıl oluşturulduğunu bilmek istiyorsanız, belki kullanışlı olabilir.
gitaarik

6
tekrar teşekkürler ama 2 alan değil, muhtemelen daha fazla olacak. Yine, onları DB'de saklamak İSTEMİYORUM, bu nedenle bu çözüm benim için çalışamaz.
michalv82

6

Django 2.1.1 Birincil yanıt, sorumu yanıtlamanın yarısına geldi. Sonucu gerçek modelimdeki bir alana kaydetmeme yardımcı olmadı. Benim durumumda, bir kullanıcının veri girebileceği bir metin alanı istedim, daha sonra bir kayıt gerçekleştiğinde veriler işlenecek ve sonuç modeldeki bir alana yerleştirilecek ve kaydedilecek. Orijinal cevap, ekstra alandan değerin nasıl alınacağını gösterirken, en azından Django 2.1.1'de modele nasıl geri kaydedileceğini göstermedi.

Bu, bağlı olmayan bir özel alandan değeri alır, işler ve onu gerçek açıklama alanıma kaydeder:

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__"

4

her zaman yeni yönetici şablonu oluşturabilir ve yönetici_görünümünüzde ihtiyacınız olanı yapabilirsiniz (admin_view'e yönetici ekleme url'sini geçersiz kılın):

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

3

İki ayrı alanı değil, yalnızca birleştirilmiş alanı modelde depolamak istiyorsanız, şöyle bir şey yapabilirsiniz:

Asla böyle bir şey yapmadım, bu yüzden nasıl sonuçlanacağından tam olarak emin değilim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.