How to override the model field in django form - python

In my Model i have this
description = tinymce_models.HTMLField(help_text='A short descripton')
Now i want to render this field as normal text area not the tinymece field. I can't edit the models file.
Is there any way i can override the same field in my form.
like this
description = forms.widgets.Textarea(attrs={'rows':4, 'cols':40})
I tried this but didn't worked

you can specify what widget you want to use in modelforms Meta class. For example:
class MyModelForm(ModelForm):
class Meta:
model = MyModel
widgets = {
'description': Textarea(attrs={'rows': 4, 'cols': 40}),
}
Reference : Overriding the default field types or widgets

Related

How to populate django admin form from model property?

I have model which among other fields contains price property which is calculated dynamically. I want to display this property in model admin page. So I've created custom ModelForm:
class ShipmentForm(forms.ModelForm):
price = forms.IntegerField()
class Meta:
model = models.Shipment
fields = [
'title',
'price',
]
However I can't get price value in that form.
Here's how I change form in admin panel:
class ShipmentAdmin(admin.ModelAdmin):
form = ShipmentForm
See ModelAdmin.readonly_fields (Django 1.10 docs link).
A read-only field can not only display data from a model’s field, it can also display the output of a model’s method or a method of the ModelAdmin class itself.
This means that you can do:
class ShipmentAdmin(admin.ModelAdmin):
readonly_fields = ('price', 'something_else')
def something_else(self, instance):
# calculate something else here
Where price is a model method, and something_else is a ModelAdmin method.

Understanding UpdateView to change the Form and FormWidget

I still didn't understood the UpdateView. Where does it fetch the form from?
It has exactly the fields declared in the model, but doesn't use the form defined in forms.py.
I did however follow the answer given at:
How does one use a custom widget with a generic UpdateView without having to redefine the entire form?
In my case I use an IntegerField in model.py and use Radiobuttons in the Form.
So what the UpdateView does is giving me an IntegerField instead of a ChoiceField. Even when I assigned the RadioSelect Widget or a Choice Field:
The View:
class UpdateEinflussideen(UpdateView):
model = Einflussideen
EINFLUSS = [(10,'hoch'),(4,'mittel'),(1,'gering')]
form_class = forms.models.modelform_factory(Einflussideen,
widgets={'einfluss': forms.ChoiceField(
choices=EINFLUSS, widget=forms.RadioSelect())},
)
template_name = 'verbrauchererfassung/update_einflussideen.html'
success_url = reverse_lazy('verbraucher')
The Model:
class Einflussideen(models.Model):
idee = models.CharField(max_length=100)
einfluss = models.IntegerField()
verbraucher = models.ForeignKey(Verbraucher)
Variables in python are case-sensitive. Change the atribute form_Class to the form_class. Also the widgets argument should contain a dict with the Widget instances in the values:
form_class = forms.models.modelform_factory(Einflussideen,
widgets={'einfluss': forms.RadioSelect(choices=EINFLUSS)})

Auto populate Django ModelForms

I was wondering how to auto populate fields in a form like in this picture http://prntscr.com/lkn7x . Here is what I have so far for my forms.
class PIREPForm(ModelForm):
class Meta:
model = PIREP
In the model form you can pass the instance which will be mapped to the form fields
form = TestForm(instance = test_instance)
Otherwise, if you want to populate some fields you could pass the initial argument
form = TestForm(initial = {'field_name':field_value,...})

unmodifiable attribute in django admin

I have simply model class:
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
I want to set attribute title unmodifiable in django admin. What should I do to set this?
Add the field name to readonly_fields of that model's ModelAdmin class. According to the documentation:
By default the admin shows all fields as editable. Any fields in this option (which should be a list or tuple) will display its data as-is and non-editable.
In your situation this looks like:
readonly_fields = ("title",)

Django Admin: Using a custom widget for only one model field

I have a DateTimeField field in my model. I wanted to display it as a checkbox widget in the Django admin site. To do this, I created a custom form widget. However, I do not know how to use my custom widget for only this one field.
The Django documentation explains how to use a custom widget for all fields of a certain type:
class StopAdmin(admin.ModelAdmin):
formfield_overrides = {
models.DateTimeField: {'widget': ApproveStopWidget }
}
This is not granular enough though. I want to change it for only one field.
Create a custom ModelForm for your ModelAdmin and add 'widgets' to its Meta class, like so:
class StopAdminForm(forms.ModelForm):
class Meta:
model = Stop
widgets = {
'field_name': ApproveStopWidget(),
}
fields = '__all__'
class StopAdmin(admin.ModelAdmin):
form = StopAdminForm
Done!
Documentation for this is sort of non-intuitively placed in the ModelForm docs, without any mention to it given in the admin docs. See: Creating forms from models
After digging into the admin, model field and form field code, I believe the only way to carry out what I want is by creating a custom model field:
models.py
from django.db import models
from widgets import ApproveStopWidget
class ApproveStopModelField(models.DateTimeField):
pass
class Stop(models.model):
# Other fields
approve_ts = ApproveStopModelField('Approve place', null=True, blank=True)
admin.py
from widgets import ApproveStopWidget
from models import ApproveStopModelField
class StopAdmin(admin.ModelAdmin):
formfield_overrides = {
ApproveStopModelField: {'widget': ApproveStopWidget }
}
It gets the job done.
For the time being, I'll leave the question unanswered because I have the habit of missing the obvious. Perhaps some Django smartypants has a better solution.
Override formfield_for_dbfield like thus:
class VehicleAdmin(admin.ModelAdmin):
search_fields = ["name", "colour"]
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.name == 'colour':
kwargs['widget'] = ColourChooserWidget
return super(VehicleAdmin, self).formfield_for_dbfield(db_field,**kwargs)
(credit to http://www.kryogenix.org/days/2008/03/28/overriding-a-single-field-in-the-django-admin-using-newforms-admin/ )
Django's ModelAdmin.get_changelist_form(self, request, **kwargs) will do the trick for the case of list_editable
class StopAdminForm(forms.ModelForm):
class Meta:
model = Stop
widgets = {
'approve_ts': ApproveStopWidget(),
}
class StopAdmin(admin.ModelAdmin):
form = StopAdminForm
#just return the ModelForm class StopAdminForm
def get_changelist_form(self, request, **kwargs):
return StopAdminForm
Refer to Django Official documentation on this topic
I hope this will help
You can change the widget for only one field by assigning your widget to a field in a custom form and assigning the custom form to an admin as shown below:
# "admin.py"
class ProductForm(forms.ModelForm):
class Meta:
model = Product
widgets = {
'price': PriceWidget(),
}
fields = '__all__'
#admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
form = ProductForm

Categories

Resources