Django admin custom admin widget, how to disable required? - python

ive added a custom widget to my admin form that just displays data and when i try save the form i get field is required on my custom widget, how can i set this to not required?
Thanks
forms.py
class TemplateVariablesWidget(forms.Widget):
template_name = 'networks/config_variables.html'
def render(self, name, value, attrs=None):
c_vars = ConfigVariables.objects.all()
context = {
'ConfigVariables' : c_vars
}
return mark_safe(render_to_string(self.template_name, context))
class VariableForm(forms.ModelForm):
variables = forms.CharField(widget=TemplateVariablesWidget)
class Meta:
model = ConfigVariables
fields = "__all__"
admin.py
class ConfigTemplateAdmin(admin.ModelAdmin):
form = VariableForm
list_display = ('device_name', 'date_modified')
admin.site.register(ConfigTemplates, ConfigTemplateAdmin)
error:

Take a look at the Django docs at the Form fields section.
class VariableForm(forms.ModelForm):
variables = forms.CharField(widget=TemplateVariablesWidget, required=False)
class Meta:
model = ConfigVariables
fields = "__all__"
But, take care, check if this field is not required in models.

Related

Dynamic fields in django forms

I am trying to have a custom form on django admin for my ModelB, with fields taken from other ModelA.
models.py
class ModelA(models.Model):
source = models.CharField(max_length=80)
keys = ArrayField(
models.CharField(max_length=50)
)
class ModelB(models.Model):
characteristic_keys = JSONField()
forms.py
class ModelBForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
queryset = ModelA.objects.all()
dynamic_fields = [(x.source, x.keys) for x in queryset]
# New fields to be shown on admin =>
# Field name => "source" from modelA
# Field type => multiple choice with options => "keys" from modelA
for field in dynamic_fields:
self.fields[field[0]] = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,
choices=field[1])
def save(self, commit=True):
# ...do something with extra_field here...
return super().save(commit=commit)
class Meta:
model = Workflow
fields = "__all__"
admin.py
class ModelBAdmin(admin.ModelAdmin):
form = ModelBForm
admin.site.register(ModelB, ModelBAdmin)
I want a single form for ModelB on django admin, with dynamic "source" fields takes from ModelA, with multiple choice options from their corresponding "key" values in modelB.
I have tried to keep information clear and understandable, please let me know if I have missed any information that might be needed to understand the problem. Any ideas to deal this problem would be a great help!

Want to add a Form field in Admin along with Model fields in django

I want to add 3 fields in my Admin.py page. out of which two fields are from Model.py and one field is from form.py. But somehow when i add these fields to admin.site.register function, an error pops up saying 'userlist' is not recognizable. Below is my code :
Models.py
class About(models.Model):
about_author = models.TextField()
pic = models.FileField(upload_to = '', default = 'static/defaul.jpg')
Form.py
class PostAuthorDetails(forms.ModelForm):
def __init__(self,*args,**kwargs):
super(PostAuthorDetails,self).__init__(*args,**kwargs)
self.fields['userlist'] = forms.ModelChoiceField(queryset=User.objects.all())
class Meta:
model = About
fields = '__all__'
Admin.py
class PostAuthorDetailsAdmin(admin.ModelAdmin):
form = PostAuthorDetails
def get_fieldsets(self,*args,**kwargs):
return((None,{'fields':('about_author','pic','userlist'),}),)
admin.site.register(About,PostAuthorDetailsAdmin)
Please advise whats wrong with the code.
FormFields are class members. You can not declare FormFields during the initialisation of the Form.
class PostAuthorDetails(forms.ModelForm):
userlist = forms.ModelChoiceField(queryset=User.objects.all())
class Meta:
model = About
'__all__'
See the docs about ModelForms: https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/

Django admin: Edit fields of one-to-one model class

I have two models with the following relationship defined in models.py:
class InnerModel(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class OuterModel(models.Model):
inner = models.OneToOneField(InnerModel)
def __str__(self):
return "OuterModel"
My forms.py looks like this:
class OuterModelForm(forms.ModelForm)
class Meta:
model = OuterModel
fields = ['inner']
My admin.py form looks like this:
class OuterModelAdmin(admin.ModelAdmin)
form = OuterModelForm
admin.site.register(OuterModel, OuterModelAdmin)
When I display the admin page, I can see the InnerModel instance and the name field is present, but the name field is an empty drop-down menu rather than a blank text field that can be edited.
How can I change the InnerModel name field so that it can be edited by admin?
You need to use inlines (doc):
class InnerModelInline(admin.StackedInline):
model = InnerModel
class OuterModelAdmin(admin.ModelAdmin):
inlines = [InnerModelInline]
admin.site.register(OuterModel, OuterModelAdmin)
Similar question: here

Adding custom fields to Django admin

I have defined my model with various fields.
Some of these are custom fields, which I am using to validate credit card data, using the fields.py file of my app. Source is here.
class Transaction(models.Model):
card_name = models.CharField()
card_number = CreditCardField(required=True)
security_code = VerificationValueField(required=True)
expiry_date = ExpiryDateField(required=True)
I have defined a ModelForm in my forms.py file.
class TransactionForm(forms.ModelForm):
class Meta:
model = Transaction
fields = "__all__"
And I've added the form to my admin.py file.
class TransactionAdmin(admin.ModelAdmin):
form = TransactionForm
def get_fieldsets(self, *args, **kwargs):
return (
(None, {
'fields': ('card_name', 'card_number'),
}),
)
admin.site.register(Transaction, TransactionAdmin)
However, the custom fields don't seem to be showing in the administration panel. Having done a ton of research, I found this, which would seem to be the solution, except it doesn't work. I've tried all sorts of over things including adding a fields tuple with the missing fields to get it to work, but no dice. And yes I've done plenty of searching.
The error I get when following the solution in the last link is this:
Unknown field(s) (card_number) specified for Transaction. Check fields/fieldsets/exclude attributes of class TransactionAdmin.
Running Django 1.7.4, Python 3.
Change your model / admin / form like this
class Transaction(models.Model):
card_name = models.CharField()
card_number = models.CharField(max_length=40)
expire_date = models.DateTimeField()
card_code = models.CharField(max_length=10)
class TransactionForm(forms.ModelForm):
card_number = CreditCardField(required=True)
expiry_date = ExpiryDateField(required=True)
card_code = VerificationValueField(required=True)
class Meta:
model = Transaction
fields = "__all__"
class TransactionAdmin(admin.ModelAdmin):
form = TransactionForm
admin.site.register(Transaction, TransactionAdmin)
UPDATE:
CreditCardField is a Form field, not a model field. See its usage in the same link that you have posted.
Those fields will come in the form.

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