I have a table like that:
import django_tables2 as tables
from .models import MyModel
class MyTable(tables.Table):
class Meta:
model = MyModel
fields = ['myfield', 'relatedtable.otherfield']
Since I can not have render_relatedtable.otherfield and render_relatedtable__otherfield does not work, how can I override render_<column_name> or value_<colum_name> for relatedtable.otherfield? Is it even possible?
I tried following approaches, but none of them worked:
Override attributes in __init__()
class MyTable(tables.Table):
class Meta:
model = MyModel
fields = ['myfield', 'relatedtable.otherfield']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.columns['relatedtable.otherfield'].render = myrenderfnc
# and/or
self.columns['relatedtable.otherfield'].column.render = myrenderfnc
Custom column
class MyColumn(tables.Column):
def render(self, record):
return getattr(record, 'relatedtable.otherfield')
class MyTable(tables.Table):
class Meta:
model = MyModel
fields = ['myfield']
otherfield = MyColumn()
'Renaming' column
class MyTable(tables.Table):
class Meta:
model = MyModel
fields = ['myfield']
def __init__(self, *args, **kwargs):
exclude = ['relatedtable.otherfield']
extra_columns = [('otherfield', self.base_columns['relatedtable.otherfield')]
super().__init__(*args, exclude=exclude, extra_columns=extra_columns, **kwargs)
self.columns['relatedtable.otherfield'].render = myrenderfnc
# and/or
self.columns['relatedtable.otherfield'].column.render = myrenderfnc
One way to do it is explicitly define the column with an accessor, and then use the column name in your render_FOO method name like this:
class MyTable(tables.Table):
otherfield = MyColumn(accessor='relatedtable.otherfield')
class Meta:
model = MyModel
fields = ['myfield']
def render_otherfield(self, record, value):
return value
Your 'custom column' example example should also work though.
Related
I have a form, and a select input, i need change the queryset of tthat select, how can i make this?
my form exemple:
class myModelForm(forms.ModelForm):
class Meta:
model = myModel
fields = '__all__'
Try overriding __init__ and setting the queryset on your field:
class myModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['<your_field_name'].queryset = <your_queryset>
if you want to make a form to catch only some of the field of the model you have to specify such field:
class Meta:
model = myModel
fields = ['field1','field3','field12']
if you mean that you want to make a change into the form after you get it into your view:
form = myModelForm(request.POST)
form.cleaned_data['field1'] = 'change what you want'
Suppose I have following Model
class Member(models.Model):
name = ...
qualities = models.ManyToManyField(ProfessionalQuality, related_name='members')
And following form:
class CommonMemberForm(forms.ModelForm):
"""This form for gathering common features in both admin and member forms
"""
class Meta:
model = Member
fields = '__all__'
def __init__(self, *args, **kwargs):
super(CommonMemberForm, self).__init__(*args, **kwargs)
self.fields['qualities'].validators.append(...)
When I try to instantiate form, I get KeyError: 'qualities' are not in self.fields. Why is that?
This code works in admin.
What is the correct way of handling such fields?
Try this:
class CommonMemberForm(forms.ModelForm):
"""This form for gathering common features in both admin and member forms
"""
class Meta:
model = Member
fields = '__all__'
widgets = {
'qualities': forms.CheckboxSelectMultiple()
}
def __init__(self, *args, **kwargs):
super(CommonMemberForm, self).__init__(*args, **kwargs)
#self.fields['qualities'].widget...
This works for me:
class CommonMemberForm(AbstractUser):
class Meta:
model = Member
fields = '__all__'
def __init__(self, *args, **kwargs):
super(RegularUser, self).__init__(*args, **kwargs)
self._meta.get_field('qualities').validators = [validate_qualities]
I know how to add a 'class' or other widget attribute to an automatically built ModelForm:
class ExampleSettingForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ExampleSettingForm, self).__init__(*args, **kwargs)
self.fields['example_field'].widget.attrs['class'] = 'css_class'
class Meta:
model = Example
How do I insert a help_text= into the example_field Field?
As of Django 1.6: You can edit it within the Meta class. Try:
class ExampleSettingForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ExampleSettingForm, self).__init__(*args, **kwargs)
self.fields['example_field'].widget.attrs['class'] = 'css_class'
class Meta:
model = Example
help_texts = {
'example_field': ('Here is some help'),
}
Docs on this are at https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-fields. See release notes at http://django.readthedocs.org/en/latest/releases/1.6.html . You can set your own label, help_text and error_messages.
This is what I did in Django 1.9:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ('__all__')
help_texts = {
"my_field": "This is case sensitive..."
}
I use a ModelForm and I want to set a max_value for an IntegerField without losing the other attributes which where created from the model (verbose_name, etc.).
This is my ModelForm:
class DataForm(ModelForm):
def __init__(self, *args, **kwargs):
super(DataForm, self).__init__(*args, **kwargs)
self.fields['start_range_points'].max_value = 1000
class Meta():
model = DataModel
This doesn't work, django does not apply the validation for large numbers. If I create the field in the following way the validation works but I lose the information which was created from the Model.
class DataForm(ModelForm):
start_range_points = forms.IntegerField(min_value=0, max_value=1000)
class Meta():
model = DataModel
What can I do to achieve something similar to attempt #1?
The validator for max_value is added in IntegerField's __init__ function if max_value is present. So you will need to manually add the validator, something like:
from django.core.validators import MaxValueValidator
class DataForm(ModelForm):
def __init__(self, *args, **kwargs):
super(DataForm, self).__init__(*args, **kwargs)
validators = [ v for v in self.fields['start_range_points'].validators if not isinstance(v, MaxValueValidator) ]
validators.append( MaxValueValidator(1000) )
self.fields['start_range_points'].validators = validators
class Meta():
model = DataModel
How to validate model field title? What if for example, every use of the title field started with the word ‘Blog’.
models.py
class TitleAbstract(models.Model):
title = models.CharField(max_length=255)
class Meta:
abstract = True
class Blog(TitleAbstract):
..............
forms.py
class BlogForm(forms.ModelForm):
class Meta:
model = Blog
views.py
class BlogCreateView(CreateView):
model = Blog
action = 'created'
validators.py
from django.core.exceptions import ValidationError
def validate_title(value):
if not value.lower().startswith(u'blog'):
msg = u"Enter a value starting with 'Blog'"
raise ValidationError(msg)
forms.py
class BlogForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(BlogForm, self).__init__(*args, **kwargs)
self.fields['title'].validators = [validate_title]
class Meta:
model = Blog
views.py
class BlogCreateView(CreateView):
model = Blog
action = 'created'
form_class = BlogForm