I have created a model with some classes:
class Student(models.Model):
name = models.CharField(max_length=40)
last_name = models.CharFIeld(max_length=40)
(...)
and in the same models.py file at the bottom I've added a class corresponding to one of my models so i can create a form:
class StudentForm(ModelForm):
class Meta:
model = Student
How do I customize form fields created via ModelForm class ? I was reading django Documentation and I can't understand overriding the default types part.
For example, in documentation they say this will work:
class ArticleForm(ModelForm):
pub_date = DateField(label='Publication date')
class Meta:
model = Article
but when i type my values it's not working. I can't define my label:
class StudentForm(ModelForm):
name = CharField(label='New label')
class Meta:
model = Student
Do i have to create a file like forms.py with identical fields as in Model class and then customize them ? Is it possible to change single field css attributes like width, height using only Model Forms ?
Field for form use a difference library to create a from. You need to import django.forms and use form.XXX for specific Field
from django import forms
class StudentForm(ModelForm):
class Meta:
model = Student
subject = forms.CharField(label='New label')
In order to customize field in model form, you don't need to create it manually. Django model fields have special attributes:
verbose_name (goes to label of the field)
help_text (by default rendered as additional description below the field)
So, all you need is:
class Student(models.Model):
name = models.CharField(
max_length=40,
verbose_name="Student's Name",
help_text="Please tell me your name") # Optional
last_name = models.CharFIeld(max_length=40)
...
Then you don't need to do any customization in model form.
See: https://docs.djangoproject.com/en/dev/ref/models/fields/#verbose-name
Related
I want to be able to sort a table column defined using a custom method in the Django admin.
I narrowed down the problem to this simple example in Django:
models.py:
from django.db import models
class MyObject(models.Model):
name = models.CharField(_("name"), max_length=255)
layers = models.URLField(_("Layers"), blank=True, max_length=1024)
choices = models.TextField(
verbose_name=_("Choice values"),
blank=True,
help_text=_("Enter your choice"),
)
class Meta:
verbose_name = _("Object config")
verbose_name_plural = _("Objects config")
def __str__(self): # my custom method
return self.name
and admin.py:
from django import forms
from django.contrib import admin
class MyObjectAdminForm(forms.ModelForm):
"""Form"""
class Meta:
model = models.MyObject
fields = "__all__"
help_texts = {
"layers": "URL for the layers",
}
class MyObjectAdmin(admin.ModelAdmin):
form = MyObjectAdminForm
list_filter = ["name",]
search_fields = ["name",]
# I want the first column (__str__) to be sortable in the admin interface:
list_display = ["__str__", ...] # the ... represent some other DB fields
but for the moment I cannot sort that first column (it is grayed out, I cannot click on its title):
So how could I sort the first column in this admin table as defined by the __str__() method of the MyObject model? (please note that I cannot change the model itself. I'm also brand new to Django, so don't hesitate to detail your answer as if you were speaking to a kid.)
I have the following models
class Group(models.Model):
name = models.CharField(max_length=32, unique=True)
class Subgroup(models.Model):
name = models.CharField(max_length=32, unique=True)
group = models.ForeignKey(Group)
class Keywords(models.Model):
name = models.CharField(max_length=32, unique=True)
subgroup = models.ForeignKey(Subgroup)
For each Subgroup I need to manage a list of keywords.
I'm trying to use django forms to automatically display a list (select box) where if I add or remove values to that list and then issue a form.save that it automatically updates the models and data.
How exactly can I do this? Are my models designed properly to allow this?
I think you can create form with MultipleChoiceField:
class MyForm(forms.Form):
to_select = forms.MultipleChoiceField(widget=forms.CheckboxInput, choices=[])
In this case you have to override form`s save method.
Did you try to create model form for subgroup class?
class MyForm(forms.ModelForm):
class Meta():
model=Subgroup
I'm using Django 1.2's new ManyToMany admin.TabularInline to display related objects in the admin app, and it works great except I can't figure out what to set the "ordering" property to so it can sort by one of the cross-referenced field names.
For instance:
class Foo(models.Model):
name = models.CharField(max_length=100)
class Bar(models.Model):
title = models.CharField(max_length=100)
foos = models.ManyToManyField(Foo)
class FooBarInline(admin.TabularInline):
model = Bar.foos.through
ordering = ('name', ) # DOES NOT WORK
raw_id_fields = ('name', ) # THROWS EXCEPTION
class FooAdmin(admin.ModelAdmin):
inlines = (FooBarInline, )
class Meta:
model = Foo
How can I get to the Foo.name field to order by it in the inline?
The model ordering meta option designates the order of the inline elements.
class Foo(models.Model):
name = models.CharField(max_length=100)
class Meta:
ordering = ('name',)
If you needed to have the ordering of the admin model different from your primary ordering, you could do something like this:
class Foo_Extended(Foo):
class Meta:
ordering = ('name',)
And use Foo_Extended for your AdminInline model.
I'm assuming you know this, but Django 1.3 adds and ordering option to the InlineAdmin model but I know you said Django 1.2
I think you may override
ModelAdmin.formfield_for_foreignkey(self, db_field, request, **kwargs)
You can find details in the docs for ModelAdmin.formfield_for_foreignkey.
I have a model form that I use to update a model.
class Turtle(models.Model):
name = models.CharField(max_length=50, blank=False)
description = models.TextField(blank=True)
class TurtleForm(forms.ModelForm):
class Meta:
model = Turtle
Sometimes I don't need to update the entire model, but only want to update one of the fields. So when I POST the form only has information for the description. When I do that the model never saves because it thinks that the name is being blanked out while my intent is that the name not change and just be used from the model.
turtle_form = TurtleForm(request.POST, instance=object)
if turtle_form.is_valid():
turtle_form.save()
Is there any way to make this happen? Thanks!
Only use specified fields:
class FirstModelForm(forms.ModelForm):
class Meta:
model = TheModel
fields = ('title',)
def clean_title(self....
See http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#controlling-which-fields-are-used-with-fields-and-exclude
It is common to use different ModelForms for a model in different views, when you need different features. So creating another form for the model that uses the same behaviour (say clean_<fieldname> methods etc.) use:
class SecondModelForm(FirstModelForm):
class Meta:
model = TheModel
fields = ('title', 'description')
If you don't want to update a field, remove it from the form via the Meta exclude tuple:
class Meta:
exclude = ('title',)
As the title suggests. I want to be able to change the label of a single field in the admin application. I'm aware of the Form.field attribute, but how do I get my Model or ModelAdmin to pass along that information?
the verbose name of the field is the (optional) first parameter at field construction.
If your field is a property (a method) then you should use short_description:
class Person(models.Model):
...
def address_report(self, instance):
...
# short_description functions like a model field's verbose_name
address_report.short_description = "Address"
As Javier suggested you can use verbose name in your fields in model.py. Example as below,
class Employee(models.Model):
name = models.CharField(max_length = 100)
dob = models.DateField('Date Of Birth')
doj = models.DateField(verbose_name='Date Of Joining')
mobile=models.IntegerField(max_length = 12)
email = models.EmailField(max_length=50)
bill = models.BooleanField(db_index=True,default=False)
proj = models.ForeignKey(Project, verbose_name='Project')
Here the dob,doj and proj files will display its name in admin form as per the verbose_name mentioned to those fields.
from django.db import models
class MyClassName(models.Model):
field_name = models.IntegerField(verbose_name='Field Caption')
Building on Javier's answer; if you need one label in forms (on the front-end) and another label on admin it is best to set internal (admin) one in the model and overwrite it on forms. Admin will of course use the label in the model field automatically.
Use "verbose_name" to change a field name as the example below.
"models.py":
from django.db import models
class MyModel(models.Model): # Here
name = models.CharField(max_length=255, verbose_name="My Name")
If you want change the field label only on particular admin model without changing field of the model:
class MyModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
form.base_fields["name"].label = "New label"
return form