i have this code below, where i'm using Select2 in my select component, it's working fine, as i'm writing it's looking, but i've already searched the internet to find examples of how to customize the query set that runs in the widget, some help ?
select2 works very well
class ConsumidorWidget(s2forms.ModelSelect2Widget):
search_fields = [
"nome__icontains",
"email__icontains",
]
class ConsumoForm(forms.ModelForm):
class Meta:
model = Consumo
fields = ('id', 'consumidor', 'mesconsumo', 'anoconsumo', 'valorapagar', 'valorhidrometro',
'dataleitura', 'datamissao', 'datavencimento', 'foipago',)
exclude = ('bairro',)
mesconsumo = forms.ChoiceField()
widgets = {
"consumidor": ConsumidorWidget,
}
Use ModelChoiceField:
consumidor = forms.ModelChoiceField(
queryset=Consumo.objects.all(),
widget=ConsumidorWidget)
Or you can try overriding the __init__ method:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['consumidor'].queryset = Consumo.objects.all()
Related
I have a form with lots of repetition and I want to use the wrap function of django crispy forms to reduce this. This is the form as it stands:
class MyForm(ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Row(Field(PrependedText('field1', 'Field1title', wrapper_class='col-12 stretchprepend')),
title = self.base_fields['field1'].help_text, data_bs_toggle='tooltip',
data_bs_placement='bottom', data_html="true"),
#fields 2-29
Row(Field(PrependedText('field30', 'Field30title', wrapper_class='col-12 stretchprepend')),
title = self.base_fields['field1'].help_text, data_bs_toggle='tooltip',
data_bs_placement='bottom', data_html="true")
)
CHOICES = [tuple([x,x]) for x in range(1,8)]
help_text = {'field1': ''''help text for field 1''' #etc for other fields)
field1 = IntegerField( label='Field1title', widget=Select(choices=CHOICES), help_text=help_text['field1'])
# Repeat up to field 30
class Meta:
model = mymodel
fields = ['field1',...,'field30']
I can get wrap to generate some aspects of the form like so:
self.helper.layout('field1'...'field30')
self.helper[:].wrap(Field, wrapper_class='col-12 stretchprepend')
I cant' seem to get it to work to include all the other aspects e.g. PrependedText, title, data_bs_toggle etc Please could anyone advise?
I've been reading lots of questions like this on stackoverflow but none seem to work. All I want to do is make a filtered form dropdown. I'm not sure how do go about doing it. I get the error that main is not defined... but I'm sure that's because it's not initialized or something? I'm very confused lol.
My form code looks like this:
class AssignForm(ModelForm):
class Meta():
model = Address
fields = ['overseer','publisher', 'status']
def __init__(self, *args, **kwargs,):
super(AssignForm, self).__init__(*args, **kwargs)
self.fields['publisher'].queryset = Publisher.objects.filter(service_group=main)
Here is my View:
def assignment(request, pk_a):
assign = Address.objects.get(id=pk_a)
num = request.user.overseer.publisher_set.first()
main = num.service_group.id
print(main)
I would like to use the variable: main inside my form dropdown so I can limit the dropdown relative to the overseer. How can this be accomplished? Thanks!
form = AssignForm(main, request.POST, instance=assign)
context = {'form':form,}
return render(request, 'sms/assign.html', context )
Change your form to
class AssignForm(ModelForm):
class Meta():
model = Address
fields = ['overseer','publisher', 'status']
def __init__(self, main, *args, **kwargs,):
super(AssignForm, self).__init__(*args, **kwargs)
self.fields['publisher'].queryset = Publisher.objects.filter(service_group=main)
and change your Form instantiation in views to
form = AssignForm(main, request.POST, instance=assign)
I would like to build a form with dynamically fields depends on needs and i have tried this code but doesn't work, the model form show all fields.
forms.py:
class CustomModelForm(forms.ModelForm):
class Meta:
model = app_models.CustomModel
fields = '__all__'
def __init__(self, excluded_fields=None, *args, **kwargs):
super(CustomModelForm, self).__init__(*args, **kwargs)
for meta_field in self.fields:
if meta_field in excluded_fields:
# None of this instructions works
-> del self.fields[meta_field]
-> self.fields.pop(meta_field)
-> self.fields.remove(meta_field)
Anybody could help me ?
Thanks in advance.
Alternatively, could you use the modelform_factory?
from django.forms import modelform_factory
CustomModelForm = modelform_factory(MyModel, exclude=('field_1', 'field_2'))
That way you could determine the exclude fields before creating the form, and just pass them into the factory, no need to override the constructor then.
The problem was the list of excluded_fields came from model._meta.get_fields(), not is a list of strings, and the if condition didnt matched well because self.fields is a python ordereddict.
This code solve the problem:
class CustomModelForm(forms.ModelForm):
class Meta:
model = app_models.CustomModel
fields = '__all__'
def __init__(self, excluded_fields=None, *args, **kwargs):
super(CustomModelForm, self).__init__(*args, **kwargs)
show_fields = []
for field in excluded_fields:
show_fields.append(field.name)
for meta_field in list(self.fields):
if meta_field not in show_fields:
del self.fields[meta_field]
I am creating my form in Form.py like this:
class pdftabelModelForm(forms.ModelForm):
class Meta:
model = pdftabel_tool_
fields = ['apn', 'owner_name']
apn = forms.ModelChoiceField(queryset= Field.objects.values_list('name', flat=True), empty_label="(Choose field)")
owner_name = forms.ModelChoiceField(queryset= Field.objects.values_list('name', flat=True), empty_label="(Choose field)")
But due to some reasons like 'self' is not available in form.py. I can only access it in views.py. So I want to make it like
class FieldForm(ModelForm):
class Meta:
model = pdftabel_tool_
fields = (
'apn',
'owner_name',)
How can I make these fields as dropdown like I did in my forms.py?
Why are you set on doing it in views.py? forms.py is the appropriate place to do this.
Instead of redefining your fields, you should use the form's __init__ method to override the querysets for your fields, like so:
class pdftabelModelForm(forms.ModelForm):
class Meta:
model = pdftabel_tool_
fields = ['apn', 'owner_name']
def __init__(self, *args, **kwargs):
super(pdftabelModelForm, self).__init__(*args, **kwargs)
self.fields['apn'].queryset = X
self.fields['owner_name'].queryset = X
EDIT: if you need to pass extra parameters to your form, update the init method to this:
def __init__(self, *args, **kwargs):
self.layer_id = self.kwargs.pop('layer_id')
super(pdftabelModelForm, self).__init__(*args, **kwargs)
self.fields['apn'].queryset = X
self.fields['owner_name'].queryset = X
And when you initialize your form from views.py, pass the parameter:
form = pdftableModelForm(layer_id=X)
note : This is closely related to the answer in this question :
django admin - add custom form fields that are not part of the model
In Django it is possible to create custom ModelForms that have "rouge" fields that don't pertain to a specific database field in any model.
In the following code example there is a custom field that called 'extra_field'. It appears in the admin page for it's model instance and it can be accessed in the save method but there does not appear to be a 'load' method.
How do I load the 'extra_field' with data before the admin page loads?
# admin.py
class YourModelForm(forms.ModelForm):
extra_field = forms.CharField()
def load(..., obj):
# This method doesn't exist.
# extra_field = obj.id * random()
def save(self, commit=True):
extra_field = self.cleaned_data.get('extra_field', None)
return super(YourModelForm, self).save(commit=commit)
class Meta:
model = YourModel
class YourModelAdmin(admin.ModelAdmin):
form = YourModelForm
fieldsets = (
(None, {
'fields': ('name', 'description', 'extra_field',),
}),
)
source code by #vishnu
Override the form's __init__ method and set the initial property of the field:
class YourModelForm(forms.ModelForm):
extra_field = forms.CharField()
def __init__(self, *args, **kwargs):
super(YourModelForm, self).__init__(*args, **kwargs)
initial = '%s*rnd' % self.instance.pk if self.instance.pk else 'new'
self.fields['extra_field'].initial = initial