J'ai un modèle enregistré sur le site d'administration. L'un de ses champs est une expression de chaîne longue. J'aimerais ajouter des champs de formulaire personnalisés à la page d'ajout/mise à jour de ce modèle dans l'administrateur. Je vais ensuite créer l'expression de chaîne longue en fonction de la valeur de ces champs et la sauvegarder dans le champ de modèle approprié.
Comment puis je faire ça?
UPDATE: Fondamentalement, je construis une expression mathématique ou une chaîne à partir de symboles, l'utilisateur choisit des symboles (ce sont les champs personnalisés qui ne font pas partie du modèle) et lorsqu'il clique sur enregistrer, je crée une représentation d'expression de chaîne à partir du liste des symboles et la stocker dans la base de données. Je ne veux pas que les symboles fassent partie du modèle et de la base de données, mais uniquement de l'expression finale.
Vous pouvez ajouter une classe ModelForm dans votre fichier admin.py ou dans un autre formulaire.py, puis déclarer vos champs supplémentaires à l'intérieur comme d'habitude. J'ai également donné un exemple d'utilisation de ces valeurs dans 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
Pour que les champs supplémentaires apparaissent dans l'administrateur, il suffit de:
Comme ça:
class YourModelAdmin(admin.ModelAdmin):
form = YourModelForm
fieldsets = (
(None, {
'fields': ('name', 'description', 'extra_field',),
}),
)
UPDATE: Dans Django 1.8, vous devez ajouter fields = '__all__'
à la métaclasse de YourModelForm.
Il est possible de le faire dans l’administrateur, mais il n’ya pas de solution simple. De même, je vous conseille de conserver la plupart des logiques d’entreprise dans vos modèles afin que vous ne dépendiez pas de Django Admin.
Peut-être que ce serait plus facile (et peut-être même mieux) si vous aviez deux champs distincts sur votre modèle. Ajoutez ensuite une méthode sur votre modèle qui les combine.
Par exemple:
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)
Ensuite, dans l’administrateur, vous pouvez ajouter le combined_fields()
sous forme de champ en lecture seule:
class MyModelAdmin(models.ModelAdmin):
list_display = ('field1', 'field2', 'combined_fields')
readonly_fields = ('combined_fields',)
def combined_fields(self, obj):
return obj.combined_fields()
Si vous souhaitez stocker le combined_fields
Dans la base de données, vous pouvez également l'enregistrer lors de l'enregistrement du modèle:
def save(self, *args, **kwargs):
self.field3 = self.combined_fields()
super(MyModel, self).save(*args, **kwargs)
vous pouvez toujours créer un nouveau modèle d'administrateur et faire ce dont vous avez besoin dans votre admin_view (remplacez l'URL d'ajout d'administrateur à votre admin_view):
url(r'^admin/mymodel/mymodel/add/$' , 'admin_views.add_my_special_model')
Si vous souhaitez uniquement stocker le champ combiné sur le modèle et non les deux champs distincts, vous pouvez procéder comme suit:
form
de votre ModelAdmin
( https://docs.djangoproject.com/en/dev/ref/ref/contrib/admin/#Django.contrib .admin.ModelAdmin.form )save_formset
méthode sur votre ModelAdmin
( https://docs.djangoproject.com/en/dev/ref/contrib/admin/#Django.contrib.admin.ModelAdmin.save_model )Je n'ai jamais fait quelque chose comme ça, donc je ne suis pas tout à fait sûr de savoir comment ça va marcher.
Django 2.1.1 La réponse principale m'a amené à mi-chemin à répondre à ma question. Cela ne m'a pas aidé à enregistrer le résultat dans un champ de mon modèle actuel. Dans mon cas, je voulais un champ de texte dans lequel un utilisateur puisse entrer des données, puis lorsqu’une sauvegarde était effectuée, les données étaient traitées et le résultat placé dans un champ du modèle, puis sauvegardé. Alors que la réponse originale montrait comment obtenir la valeur du champ extra, elle ne montrait pas comment la sauvegarder au moins dans le modèle Django 2.1.1
Cela prend la valeur d'un champ personnalisé non lié, traite et l'enregistre dans mon champ de description réel:
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__"