I'm trying do this:
class NoClearableFileInput(ClearableFileInput):
initial_text = ''
input_text = ''
class ImageUploadForm(forms.ModelForm):
title = forms.CharField(label="TITLE", required=False,widget=forms.TextInput(attrs={'placeholder': 'name'}), label_suffix="")
image = forms.ImageField(label='NEW FILE',widget=NoClearableFileInput, label_suffix="")
class Meta:
model = Image
fields = ('title','image')
There in class NoClearableFileInput cleaned value initial_text.
In fields 'title' and 'image' use label_suffix, but from initial_text symbol ":" remained.
result
How get rid of the colons?
This just worked for me with Django 2.2:
class ImageUploadForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.label_suffix = "" # Removes : as label suffix
# ...the rest of the form code...
You have to override the label_suffix on initialization. Try making the following changes:
class ImageUploadForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
kwargs.setdefault('label_suffix', '')
super(ImageUploadForm, self).__init__(*args, **kwargs)
# ... (the rest of your code) ...
There is label_suffix=":" parameter to form's __init__ method - https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.label_suffix
So, to remove trailing colon from label, you can pass label_suffix="" when initializing form in the view, for example:
class SomeView(FormView):
...
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["label_suffix"] = ""
return kwargs
Or, you can override this parameter in form's __init__ method:
class SomeForm(forms.Form):
def __init__(self, *args, **kwargs):
kwargs["label_suffix"] = ""
super().__init__(*args, **kwargs)
Related
I am trying to set the initial value of a field on a form. The field is not part of the model, but when I try and set it to a value the field is blank. From my research it could be because the form is "bound" which makes some sense to me, but in this case the field is not part of the model.
My form:
#Form for editing profile
class CatForm(forms.ModelForm):
pictureid = forms.CharField()
class Meta:
model = Cat
fields = ['name']
def __init__(self, *args, **kwargs):
picid = kwargs.pop("pictureid")
print(picid)
super(CatForm, self).__init__(*args, **kwargs)
self.fields['pictureid'] = forms.CharField(initial=picid, required=False)
The model:
class Cat(models.Model):
name = models.CharField(max_length=34,null=False)
From the view it is called like this:
catform = CatForm(request.POST, pictureid=instance.id)
I was expecting it to set the field to the value of the initial attribute, but it doesn't. I have tried testing it by directly adding a string, but doesn't set.
This is what seems to be working for me:
class CatForm(forms.ModelForm):
class Meta:
model = Cat
fields = ['name']
def __init__(self, *args, **kwargs):
picid = kwargs.pop("pictureid")
super(CatForm, self).__init__(*args, **kwargs)
self.fields['pictureid'] = forms.CharField(initial=picid)
I also needed to drop the "request.POST" from the call to this when initiating the form.
If you want to render the pictureid in GET request, then you can try like this:
catform = CatForm(initial={'pictureid': instance.id})
For GET request, you don't need to override the __init__ method.
But, if you want to use the Catform in POST request, to use the value of pictureid somewhere else(lets say in save method), then you will need to override __init__ method here.
class CatForm(forms.ModelForm):
pictureid = forms.CharField()
class Meta:
model = Cat
fields = ['name']
def __init__(self, *args, **kwargs):
picid = kwargs.pop("pictureid")
print(picid)
super(CatForm, self).__init__(*args, **kwargs)
self.pictureid = picid
def save(self, *args, **kwargs):
print(self.pictureid) # if you want to use it in save method
return super().save(*args, **kwargs)
how Form class attributes work in django ?
class Test(forms.Form):
x = forms.CharField(max_length=20)
def __init__(self, *args, **kwargs):
super(Test, self).__init__(*args, **kwargs)
print hasattr(self, 'x') #
return False ... what type of mechanism works here ?
I think you want to access the form fields in the __init__ method. You should access it from the fields attribute. Like this:
class Test(forms.Form):
x = forms.CharField(max_length=20)
def __init__(self, *args, **kwargs):
super(Test, self).__init__(*args, **kwargs)
print self.fields['x']
I try to make the form with objectl linked to only current base object (exclude others from their model):
forms.py
class RoomTypeForm(ModelForm):
class Meta:
model = RoomType
fields = {'Name', 'Rooms', 'Beds', 'Facilities', 'Capacity'}
exclude = ('Building',)
def __init__(self, *args, **kwargs):
self.building_id = kwargs.pop('building_id')
self.fields['Capacity'].queryset = Capacity.objects.filter(
Building=self.building_id
)
views.py
def building_details(request, hotel_id, building_id):
capacity_form = CapacityForm
roomtype_form = RoomTypeForm
args = {}
args.update(csrf(request))
args['building'] = Building.objects.get(id=building_id)
args['capacity'] = Capacity.objects.filter(Building=building_id)
args['roomtypes'] = RoomType.objects.filter(Building=building_id)
args['capform'] = capacity_form
args['rtform'] = roomtype_form(building_id=building_id)
return render_to_response('building.html', args)
But I have the error:
'RoomTypeForm' object has no attribute 'fields'
in line:
self.fields['Capacity'].queryset =
Capacity.objects.filter(Building=self.building_id)
How may it be possible to make all of this will be working? Please help.
You need to call the super() class in __init__
def __init__(self, *args, **kwargs):
self.building_id = kwargs.pop('building_id')
super(RoomTypeForm, self).__init__(*args, **kwargs)
self.fields['Capacity'].queryset = Capacity.objects.filter(Building=self.building_id)
Or if you are using python3, you could just do:
super().__init__(*args, **kwargs)
Another side note, it is standard practice to specify a list or a tuple in the fields. You specified a set.
I have a django form class only with one widget. I would like to give a name to this widget like <select name="custom_name"></select> but Django takes the name of the variable and gives it as a name to the widget. For example:
class MultiSelectForm(forms.Form):
here_is_the_name_of_the_widget = forms.MultipleChoiceField()
So the above code will create a widget with a name:
<select name="here_is_the_name_of_the_widget">...</select>
Because i need to prototype the form i need to create this name at initialization time.
Until this moment this form works fine but with a standard pre-given name:
class MultiSelectForm(forms.Form):
multiple_select = forms.MultipleChoiceField()
def __init__(self, attrs=None, choices=(), *args, **kwargs):
self.base_fields['multiple_select'].choices = choices
self.base_fields['multiple_select'].empty_permitted = False
self.base_fields['multiple_select'].required = kwargs.get('required', False)
self.base_fields['multiple_select'].widget = MultiSelect(attrs=attrs, choices=choices)
forms.Form.__init__(self, *args, **kwargs)
So, i thought a way (a hack) to achieve what i want but isn't working as i expected. If the name i want to give to the widget is 'countries' it produces the following error:
KeyError at <project_name>
'countries'
And the code who produces that error is:
class MultiSelectForm(forms.Form):
multiple_select = forms.MultipleChoiceField()
def __init__(self, attrs=None, choices=(), *args, **kwargs):
default_name = 'multiple_select'
name = attrs.get('name', default_name)
if name != default_name:
setattr(self, name, forms.MultipleChoiceField())
del attrs['name']
'''
The error is produced in the following line...
'''
self.base_fields[str(name)].choices = choices
self.base_fields[str(name)].empty_permitted = False
self.base_fields[str(name)].required = kwargs.get('required', False)
self.base_fields[str(name)].widget = MultiSelect(attrs=attrs, choices=choices)
forms.Form.__init__(self, *args, **kwargs)
Is there a way to achieve that, or something better?
Thanks!
Here is the solution...
thanks to #Daniel Roseman
class MultiSelectForm(forms.Form):
def __init__(self, attrs=None, choices=(), *args, **kwargs):
#empty_permitted is a Form's attribute
kwargs['empty_permitted'] = False
forms.Form.__init__(self, *args, **kwargs)
name = attrs.get('name', 'multiple_select')
self.fields[name] = forms.MultipleChoiceField(
choices=choices,
required=kwargs.get('required', False),
widget=MultiSelect(attrs=attrs, choices=choices)
)
I'm not sure why you need to do this at all, but you are definitely overcomplicating things. You can just add the field dynamically to the form when you instantiate it:
class MultiSelectForm(forms.Form):
def __init__(self, *args, **kwargs):
dynamic_field = kwargs.pop('dynamic_field')
super(MultiSelectForm, self).__init__(*args, **kwargs)
self.fields[dynamic_field['name']] = forms.MultipleChoiceField(
choices=dynamic_field['choices'],
empty_permitted=False
required=dynamic_field['required'],
widget=MultiSelect(attrs=dynamic_field['attrs']))
and then pass a dictionary on instantiation:
my_form = MultiSelectForm(
dynamic_field={'name': 'countries', 'choices': (mychoices), 'required': True})
First the code:
class CommentForm(forms.ModelForm):
categories = forms.ModelChoiceField(queryset = Category.objects.all(), required = False)
class CommentAdmin(admin.ModelAdmin):
form = CommentForm
When I'm editing my comment I'd like it categories field have the initial value of what's been selected when I saved it for the last time. How do I do that?
def get_form(self, *args, **kwargs):
f = super(CommentAdmin, self).get_form(*args, **kwargs)
f.base_fields['categories'].initial = 1
return f
This code placed in CommentAdmin did the trick...
EDIT:
def __init__(self, *args, **kwargs):
super(CommentForm, self).__init__(*args, **kwargs)
self.fields['categories'].initial = self.instance.object_id
Or this code placed in CommentForm
You want to have the current model value selected by default in the generated form? If that's the case I think what you are looking for in your view is
form = CommentForm(instance = commentinstance)
Where commentinstance is the instance that you are editing.
(This would be form = CommentForm(request.POST, instance = commentinstance) in case of a POST request)
EDIT:
If you want to do this in the form, you can just provide the instance argument from __init__, like so:
def __init__(self, *args, **kwargs):
instance = kwargs.pop('instance', YOUR_DEFAULT_INSTANCE)
super(CommentForm, self).__init__(instance = instance, *args, **kwargs)
That even leaves the default instance if you do provide one from your view.
I guess there are a few ways to solve this.
Here is how I done before:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
if 'ref' in kwargs:
ref = kwargs['ref']
item = MyModel.objects.get(pk=ref)
kwargs['instance'] = item
super(MyForm, self).__init__(*args, **kwargs)
class Meta:
model = MyModel
The important part is to put your populated model object into the keyword variable instance.