I am using forms in my Django project, and I want to specify some of the attributes of the widget that I use in my form but am having trouble figuring out how to pass in the attrs dictionary to the widget.
The view.py:
form_schedule_start = WINDOW_Schedule_Form(section_label=" Start",required=True,initial=scheduleStart,attributes={'class':"form-control",'placeholder':".col-md-4"})
The form:
class WINDOW_Schedule_Form(forms.Form):
def __init__(self,*args,**kwargs):
section_label = kwargs.pop('section_label')
initial_value = kwargs.pop('initial')
required_value = kwargs.pop('required')
attributes = kwargs.pop('attributes')
super(WINDOW_Schedule_Form,self).__init__(*args,**kwargs)
self.fields['WINDOW_Schedule'].label=mark_safe(section_label)
self.fields['WINDOW_Schedule'].initial=initial_value
self.fields['WINDOW_Schedule'].required=required_value
self.fields['WINDOW_Schedule'].attrs=attributes
WINDOW_Schedule = forms.CharField(widget=forms.TextInput())
Normally you would just do
WINDOW_Schedule = forms.CharField(widget=forms.TextInput(attrs={'class':"form-control text-center",'placeholder':".col-md-8"}))
but I want to be able to specify the 'class' and 'placeholder' attributes in my views.py.
I keep getting an error that attributes is not defined though. Can anyone tell me what I'm doing wrong?
This Code May Help You Out
class ContactForm(ModelForm):
class Meta:
model = Contact
created = MyDatePicker()
class Uniform(forms):
def __init__(self, *args, **kwargs):
attrs = kwargs.pop("attrs",{})
attrs["class"] = "span3"
kwargs["attrs"] = attrs
super(Uniform, self).__init__(*args, **kwargs)
class MyDatePicker(Uniform,forms.DateInput)
def __init__(self, *args, **kwargs):
attrs = kwargs.pop("attrs",{})
attrs["class"] = "datepick"
attrs["id"] =kwargs.get('datetag', '')
kwargs["attrs"] = attrs
super(MyDatePicker, self).__init__(*args, **kwargs)
Related
I have one model name is cityform
i want to get url parmeter in this CityFrom hwo can i do this?
here is my url
path('state/city/<int:id>/', City.as_view(), name="city")
http://localhost:8000/country/state/city/3/
here is my form
class
CityFrom(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(CityFrom,self).__init__(*args, **kwargs)
print(args)
print(kwargs)
self.fields['state'] = forms.ModelChoiceField(
empty_label = 'Select',
queryset = State.objects.all()
)
class Meta:
model = City
fields = ('state', 'name')
in this form i want to access id = 3
here is my view
from django.views import View
class City(View):
def get(self, request, *args, **kwargs):
Forms = CityFrom()
return render(request, 'albums/add.html', {'Forms': Forms})
Pass url parameter as keyword argument from views.py as following.
form = CityFrom(id=kwargs.get("id"))
To get the id in your forms.py, use following code in your form's __init__ method.
self.id = kwargs.get('id')
Your form should look like this.
CityFrom(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.id = kwargs.get('id')
super(CityFrom,self).__init__(*args, **kwargs)
self.fields['state'] = forms.ModelChoiceField(
empty_label = 'Select',
queryset = State.objects.all()
)
class Meta:
model = City
fields = ('state', 'name')
* Call super after getting the id in your form as above. Here order of calling super is important.
Try
CityFrom(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.id = kwargs.pop('id')
super(CityFrom,self).__init__(*args, **kwargs)
I am trying to make the 'cost_name' field choices to be filtered based on the dynamic project_id.
models.py
class ProjectCost(models.Model):
project_name = models.ForeignKey(ProjectName, on_delete=models.CASCADE,null=True)
cost_name = models.CharField('Cost Name', max_length=50)
total_budget = models.DecimalField('Total Budget', max_digits=9,decimal_places=2)
forms.py
class CreateCostForm(forms.ModelForm):
def __init__(self,project_id,*args, **kwargs):
super(CreateCostForm, self).__init__(*args, **kwargs)
self.fields['cost_name'].queryset = ProjectCost.objects.filter(project_name_id=project_id)
class meta:
model = ProjectCost
When i hard-code the value of project_id like:
self.fields['project_name'].queryset = ProjectCost.objects.filter(project_name_id=4) or
ProjectCost.objects.filter(project_name_id= 8),
i get the correct filtered options on the form.So how can i make project_id dynamic?
i tried:
def __init__(self, *args, **kwargs):
project_id = kwargs.pop('project_id', None)
super(CreateCostForm, self).__init__(*args, **kwargs)
self.fields['cost_name'].queryset = ProjectCost.objects.filter(project_name_id=project_id)
But this returns 'None' for the value of 'project_id'. Any idea on how to fix this?
Thanks.
As you are sub-classing from CreateView, then there is a method call get_form_kwargs() to send data from View to Form. Just override it like this:
class YourView(CreateView):
...
def get_form_kwargs(self, *args, **kwargs):
form_kwargs = super(YourView, self).get_form_kwargs(*args, **kwargs)
form_kwargs['project_id'] = self.kwargs.get('project_id') # assuming you send the project_id through url ie path('project/<int:project_id>/create/', YourView.as_view())
return form_kwargs
In that way you will be get data in project_id in Form:
Class CreateCostForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
project_id = kwargs.pop('project_id', None)
class Model_Neural_form(forms.ModelForm):
allMod = forms.ModelChoiceField(queryset=Model_Neural.objects.all())
class Meta:
model = Model_Neural
fields = ["nom_mod", "modl"]
def __init__(self, *args, **kwargs):
super(Model_Neural_form, self).__init__(*args, **kwargs)
self.fields['allMod'].label = ''
If you want to set the default initial value you should be defining initial like other form fields.
You need to set initial when you create your form like this:
allMod = forms.ModelChoiceField(
initial=instance.pk if instance else None,
queryset=Model_Neural.objects.all()
)
class Report(models.Model):
# ....
product = models.ForeignKey(Product)
class Product(models.Model):
name = models.CharField(max_length=50)
class Item(models.Model):
box = models.ForeignKey(BoxInTransport)
product = models.ForeignKey(Product)
class BoxInTransport(models.Model):
transport = models.ForeignKey(Transport)
box = models.ForeignKey(Box)
This is - in short - the structure of models.
And I have a view which lets me create new report:
class ReportCreateView(CreateView):
model = Report
form_class = ReportForm
def get_form_kwargs(self):
# updating to get argument from url
kwargs = super(DifferenceCreateView, self).get_form_kwargs()
kwargs.update(self.kwargs)
return kwargs
and the form:
class ReportForm(ModelForm):
class Meta:
model = Report
fields = [
'product'
]
def __init__(self, box_nr=None, *args, **kwargs):
super(ReportForm, self).__init__(*args, **kwargs)
self.fields['product'].queryset = ???
How can I get only these products which belong to a specific box? To be more clear:
Only products which:
Item.objects.filter(box__box__box_code=box_nr)
Now I get all Items which I need, but I need to pass self.fields['products'] to only product form with this new Items queryset.
Can you help me?
EDIT
I've tried something like this:
def __init__(self, box_nr=None, *args, **kwargs):
super(ReportForm, self).__init__(*args, **kwargs)
queryset = Item.objects.filter(
box__box__box_code=boxno
)
none_queryset = Product.objects.none()
list_or_products = [p.product for p in queryset]
product_queryset = list(chain(none_queryset, list_or_products))
self.fields['product'].queryset = product_queryset
But, first - it looks little ugly :), second - it doesn't work:
AttributeError: 'list' object has no attribute 'all'
Your __init__ could look something like this:
def __init__(self, box_nr=None, *args, **kwargs):
super(ReportForm, self).__init__(*args, **kwargs)
qs = Product.objects.filter(item__box__box__box_code=box_nr)
self.fields['product'].queryset = qs
Basically, you need a reverse lookup on Product to Item. You can read the relevant documentation here
Note that: item__box__box__box_code=box_nr is based on my understanding of your models. item__box does the reverse lookup. Rest might need some tweaking based on your model definitions.
So, I have the following form:
class DesignItemForm (forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DesignItemForm, self).__init__(*args, **kwargs)
CHOICES=[(i,i) for i in range(MAX_DESIGN_ITEM_QUANTITY)]
self.fields['quantity'] = forms.ChoiceField(choices=CHOICES)
class Meta:
model = DesignItem
fields = ('quantity','trackable',)
My view:
d = Design.object.get(slug=fromInput)
....
DesignItemInlineFormSet = inlineformset_factory(Design, DesignItem, fk_name="design", form=DesignItemForm,)
if request.method == "POST":
formset = DesignItemInlineFormSet(request.POST, request.FILES, instance=d)
if formset.is_valid():
formset.save()
DesignItemInlineFormSet(instance=d)
As you can tell, in my form, I overwrote the quantity field to be a drop down instead of an integer field.
For some reason, when I submit the form, the data is not updated in the database. However, if I change the form to the following, it works (of course, it doesn't have the dropdowns I want, but it posts to the db). Why is this, and how do I fix it?
class DesignItemForm (forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DesignItemForm, self).__init__(*args, **kwargs)
# CHOICES=[(i,i) for i in range(MAX_DESIGN_ITEM_QUANTITY)]
# self.fields['quantity'] = forms.ChoiceField(choices=CHOICES)
class Meta:
model = DesignItem
fields = ('quantity','trackable',)
EDIT: Here is the DesignItem model:
class DesignItem(models.Model):
"""Specifies how many of an item are in a design."""
design = models.ForeignKey(Design, related_name="items")
quantity = models.PositiveIntegerField(default=1)
trackable = models.ForeignKey(Trackable, related_name="used")
have you tried just overriding the widget instead of the whole field?
i guess you want a select widget
def __init__(self, *args, **kwargs):
super(DesignItemForm, self).__init__(*args, **kwargs)
CHOICES=[(i,i) for i in range(MAX_DESIGN_ITEM_QUANTITY)]
self.fields['quantity'].widget = forms.Select(choices=CHOICES)