get parameter from url into hidden parameter of form - django

I have a CreateView where I want to create a new price for a product. The product detail page has a button to change the price which leads to a new page like ...\partprice\X where X is the id of the product. A product can have multiple prices, which is the reason why I am using a CreateView. Is the only way to grab the part_id from the URL (like here)?
In the forms.py:
class PPriceFormset(ModelForm):
required_css_class = "required"
class Meta:
model = PPrice
fields = ("price", "customer", "date", "part")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'POST'
self.helper.layout = Layout(Row(Column('price'),
Column('customer')),
Submit('submit', 'Save price', css_class='btn-primary'),
Field("date", type="hidden"),
Field("part", type="hidden"))
I want to add the X from above into the hidden field "part". In the view I already have it:
class PPrice(CreateView):
model = PPrice
template_name ="gap/pprice_update.html"
form_class = PPriceFormset
success_url = reverse_lazy('part-list')
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(PPriceCreateView, self).get_form_kwargs(*args, **kwargs)
kwargs['part_id'] = self.kwargs.get("part_pk")
return kwargs

The solution was quite easy, the class needed an initial value that could be passed on to the form via get_initial.
class PPriceCreateView(CreateView):
model = PPrice
template_name ="gap/pprice_update.html"
form_class = PPriceFormset
success_url = reverse_lazy('part-list')
def get_initial(self):
return {"part": self.kwargs["part_pk"]}

Related

Django, how to set value in forms.ModelForm

I have a question for you. I have the following Model:
class Centro_di_costo(models.Model):
centro_di_costo = models.CharField('Centro di costo', max_length=30)
def __str__(self):
return self.centro_di_costo
class AltriCosti(models.Model):
STATUS_CHOICES= [
('VARIABILE', 'VARIABILE'),
('FISSO', 'FISSO'),
]
centro_di_costo = models.ForeignKey(Centro_di_costo)
sub_centro_di_costo = models.CharField('Categoria', max_length=30)
status = models.CharField(choices=STATUS_CHOICES)
price=models.DecimalField()
quantity=models.IntegerField()
I use it in a lot of view, but in one of them I wanna set the value without passing from the POST request.
So I have tried to set the ModelForm in the following manner:
class ModCollaboratori(forms.ModelForm):
class Meta:
model = AltriCosti
fields = "__all__"
def __init__(self, *args, **kwargs):
super(ModCollaboratori, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_show_labels = False
self.fields['centro_di_costo'].value= "Servizi di Produzione"
self.fields['sub_centro_di_costo'].value = "Collaboratori esterni"
self.fields['status'].value = "VARIABILE"
But It does not work. How could I fix the code to work?
You can exclude fields from your form:
class ModCollaboratori(forms.ModelForm):
class Meta:
model = AltriCosti
exclude = ['centro_di_costo', 'sub_centro_di_costo', 'status']
Then in your view you can "inject" value for these fields:
def some_view(request):
if request.method == 'POST':
form = ModCollaboratori(request.POST, request.FILES)
if form.is_valid():
form.instance.sub_centro_di_costo = 'Collaboratori esterni'
form.instance.status = 'VARIABILE'
form.instance.centro_di_costo = Centro_di_costo.objects.get_or_create(
centro_di_costo='Servizi di Produzione'
)[0]
form.save()
return redirect('name-of-some-view')
else:
form = ModCollaboratori()
return render(request, 'some_template.html', {'form': form})
for your code
self.fields['status'].value = "VARIABLE"
to make it work change to
self.instance.status = "VARIABLE"
Result:
Status: VARIABLE
basically ModelForm.__init__() will populate instance values into form.
but if we add extra field to this form, we will need to populate it by ourself in kwargs["initial"],
because this field not include in the model.
class SomeForm(forms.ModelForm):
custom_field = forms.CharField()
def __init__(self, *args, **kwargs):
kwargs["initial"]["custom_field"] = "xxxxx"
super().__init__(*args, **kwargs)

how to get url parameter in modelform

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)

How to perform queries in django modelform?

I tried this in my modelform:
class Ledgerform(forms.ModelForm):
class Meta:
model = ledger1
fields = ('name', 'group1_Name')
def __init__(self, User, Company, *args, **kwargs):
self.User = kwargs.pop('User', None)
self.Company = kwargs.pop('Company', None)
super(Ledgerform, self).__init__(*args, **kwargs)
self.fields['name'].widget.attrs = {'class': 'form-control',}
self.fields['group1_Name'].queryset = group1.objects.filter(User= self.User,Company = self.Company)
In my views.py I have done something like this:
class ledger1ListView(LoginRequiredMixin,ListView):
model = ledger1
paginate_by = 15
def get_queryset(self):
return ledger1.objects.filter(User=self.request.user, Company=self.kwargs['pk'])
class ledger1CreateView(LoginRequiredMixin,CreateView):
form_class = Ledgerform
def form_valid(self, form):
form.instance.User = self.request.user
c = company.objects.get(pk=self.kwargs['pk'])
form.instance.Company = c
return super(ledger1CreateView, self).form_valid(form)
I want to perform the the same query that I have passed in my ledger1ListView by using queryset in my modelform but my kwargs.pop is not returning the current user or the company...
This is my models.py:
class ledger1(models.Model):
User = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=True,blank=True)
Company = models.ForeignKey(company,on_delete=models.CASCADE,null=True,blank=True,related_name='Companys')
name = models.CharField(max_length=32)
group1_Name = models.ForeignKey(group1,on_delete=models.CASCADE,blank=True,null=True)
Do any one know what I am doing wrong in my code?
Thank you in advance
You can override the FormMixin.get_form_kwargs [Django-doc] in your view, that it constructs a dictionary with the parameters necessary to initialize the form, like:
class ledger1CreateView(LoginRequiredMixin,CreateView):
form_class = Ledgerform
def get_form_kwargs(self):
data = super(ledger1CreateView, self).get_form_kwargs()
data.update(
User=self.request.User,
Company=company.objects.get(pk=self.kwargs['pk'])
)
return data
The form_valid function is called after the form is constructed, validated and appears to be valid. Typically it is used to redirect the user to the "success page".

set variable into queryset of forms.py from my generic view or url

I want to set a dynamic variable into queryset of forms.py , I used __init__ to pass the dynamic variable , I think the code in forms.py is correct, the problem is how to pass the variable in views?
forms.py :
class ContainerForm(forms.ModelForm):
vehicle=forms.ModelChoiceField(required=False,queryset=Vehicle.objects.all(),widget=forms.Select(attrs={'class':'form-control'}))
def __init__(self, *args, **kwargs):
vehicle_id = kwargs.pop('vehicle_id',None)
super(ContainerForm, self).__init__(*args, **kwargs)
if vehicle_id:
self.fields['vehicle'].queryset = Vehicle.objects.filter(id=vehicle_id)
views.py
class ContainerCreate(CreateView):
form_class = ContainerForm(id= vehicle_id)
template_name = 'vehicule_app/container_form.html'
the error said :
Exception Value:'ContainerForm' object is not callable
If you want to use the vehicle_id from the URL, then you can exclude the field from the model form:
class ContainerForm(forms.ModelForm):
class Meta:
model = Container
exclude = ['vehicle']
You can then fetch the parameter from self.kwargs, and set the value on the form's instance in get_form_kwargs:
class ContainerCreate(CreateView):
form_class = ContainerForm
template_name = 'vehicule_app/container_form.html'
def get_form_kwargs(self):
kwargs = super(ContainerCreate, self).get_form_kwargs()
if kwargs['instance'] is None:
kwargs['instance'] = Container()
kwargs['instance'].vehicle_id = self.kwargs['pk'] # Fetch the vehicle_id from the URL
return kwargs
Note that the above code will not validate the id from the URL. The user could change it to any value they like.
If you want to keep the vehicle field in the form but with a single choice, then override the __init__ method and set the queryset.
class ContainerForm(forms.ModelForm):
class Meta:
model = Container
def __init__(self, *args, **kwargs):
vehicle_id = kwargs.pop('vehicle_id')
self.fields['vehicle'].queryset = Vehicle.objects.filter(id=vehicle_id)
Then in the get_form_kwargs method, add vehicle_id to kwargs instead:
class ContainerCreate(CreateView):
form_class = ContainerForm
template_name = 'vehicule_app/container_form.html'
def get_form_kwargs(self):
kwargs = super(ContainerCreate, self).get_form_kwargs()
kwargs['vehicle_id'] = self.kwargs['pk']
return kwargs

Django ModelForm with field overwrite does not post data

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)