post method of class based view is not working.while get method is responding.form is launched using get method but post is not - django-forms

Here checkout form open but problem is data entered do not save in database. I have used post method in checkout.html and model of form is created in database. But data put by user do not save in database.
views.py
class CheckoutView(View):
def get(self,*args,**kwargs):
form = CheckoutForm()
context = {
'form': form
}
print("get is working")
return render(self.request,"checkout.html",context)
def post(self,*args,**kwargs):
form = CheckoutForm(self.request.POST or None)
print("Now post is also working")
#NOT WORKING
if form.is_valid():
street_address = form.cleaned_data.get('street_address')
apartment_address = form.cleaned_data.get('apartment_address')
country = form.cleaned_data.get('country')
zip = form.cleaned_data.get('zip')
billing_address = BillingAddress(
user = self.request.user,
street_address = street_address,
apartment_address = apartment_address,
country = country,
zip = zip
)
billing_address.save()
return redirect('core:checkout')
messages.warning(self.request,"failed checkout")
return redirect('core:checkout')

Related

get new value in django admin widget

I am working on creating a widget so clients can easily modify model's Json field in django admin.
Env Info:
django-version: 3.1.14
Before drive into the widget, this is a simplify version of my model:
class Property(PolymorphicModel):
"""Basic information about property"""
...
address = models.JSONField(blank=True, null=True, default=dict,)
...
And this how I am declaring the form:
class PropertyForm(forms.ModelForm):
class Meta:
model = Property
fields = [
"address",
]
widgets = {
'address': JSONEditorWidget(),
}
I've already manage to convert json file into django admin inputs by using the following code:
class JSONEditorWidget(forms.widgets.Input):
def as_field(self, name, key, value):
""" Render key, value as field """
new_name = name + '__' + key
self.attrs = self.build_attrs({new_name:key})
self.attrs['value'] = utils.encoding.force_text(value)
return u'%s: <input%s />' % (new_name, forms.utils.flatatt(self.attrs))
def to_fields(self, name, json_obj):
"""Get list of rendered fields for json object"""
inputs = []
for key, value in json_obj.items():
inputs.append(self.as_field(name, key, value))
return inputs
def value_from_datadict(self, data, files, name):
"""I've been trying to get new values in this function but nothing successful"""
return json.dumps(prev_dict)
def render(self, name, value, attrs=None, renderer = None):
# TODO: handle empty value (render text field?)
if value is None or value == '':
value = '{}'
json_obj = json.loads(value)
inputs = self.to_fields(name, json_obj)
# render json as well
inputs.append(value)
return utils.safestring.mark_safe(u"<br />".join(inputs))
with this I could go from this:
To this:
My problem now is to catch the new values when user clicks on save/save and continue, so I can convert them into json file to save new records on postgres.
Ive tried with the function value_fromdatadict() but couldn't manage a way to get new values in the input box...
If anyone can helps me I will be so glad, I've been dealing with this a while and this is driving me crazy

How to load a dynamic saved dropdown during edit

In my app, i have a chained dropdown in which i am getting the second dropdown via jquery ajax, which works well.So i am trying to edit this saved data and load it back to an edit form, but the dropdown is showing empty. This is what i have done so far
Here is my model.py
class SchoolFees(models.Model):
fid = models.ForeignKey(FacultyData, on_delete= models.SET_NULL, null=True)
did = models.ForeignKey(DepartmentData, on_delete= models.SET_NULL, null=True)
sid = models.ForeignKey(SessionData, on_delete= models.SET_NULL, null=True)
amount = models.CharField(max_length=30)
def __str__(self):
return self.amount
forms.py
class FeesCreationForm(forms.ModelForm):
fid = forms.ModelChoiceField(queryset=FacultyData.objects.all(), empty_label="--Select Faculty--",
widget=forms.Select(attrs={'class': 'form-control'}))
did = forms.ModelChoiceField(queryset=DepartmentData.objects.all(), empty_label="--Select Faculty First--",
widget=forms.Select(attrs={'class': 'form-control'}))
sid = forms.ModelChoiceField(queryset=SessionData.objects.all(), empty_label="--Select Session--",
widget=forms.Select(attrs={'class': 'form-control'}))
class Meta:
model = models.SchoolFees
fields = ['sid', 'fid', 'did', 'amount']
widgets = {
'amount': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter Amount'})
}
def __init__(self, *args, **kwargs):
super(FeesCreationForm, self).__init__(*args, **kwargs)
self.fields['did'].queryset = DepartmentData.objects.none()
# Get did queryset for the selected fid
if 'fid' in self.data:
try:
fd = int(self.data.get('fid'))
self.fields['did'].queryset = DepartmentData.objects.filter(fid_id=fd).order_by('id')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and use empty queryset
Here is my view.py
def edit_fee(request, pk):
app = settings.CONFIG
post = get_object_or_404(SchoolFees, pk=pk)
if request.method == 'POST':
form = FeesCreationForm(request.POST, instance=post)
if form.is_valid():
form.save()
messages.add_message(request, messages.WARNING, "Fees record updated successfully")
return redirect('bursary:create_fee')
else:
# bring edit form out
form = FeesCreationForm(instance=post)
table = FeesTable(SchoolFees.objects.all())
RequestConfig(request, paginate={'per_page': 10}).configure(table)
context = {"form": form, "fees": table, 'app': app}
return render(request, 'editfee.html', context)
I expect that the saved value is pass to the dropdown with other form fields which are already showing
After going through this post, i was able to solve it when reading the comments. All i needed was to add a backward relationship to my init function.
class FeesCreationForm(forms.ModelForm):
fid = forms.ModelChoiceField(queryset=FacultyData.objects.all(), empty_label="--Select Faculty--",
widget=forms.Select(attrs={'class': 'form-control'}))
did = forms.ModelChoiceField(queryset=DepartmentData.objects.all(), empty_label="--Select Faculty First--",
widget=forms.Select(attrs={'class': 'form-control'}))
sid = forms.ModelChoiceField(queryset=SessionData.objects.all(), empty_label="--Select Session--",
widget=forms.Select(attrs={'class': 'form-control'}))
class Meta:
model = models.SchoolFees
fields = ['sid', 'fid', 'did', 'amount']
widgets = {
'amount': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter Amount'})
}
def __init__(self, *args, **kwargs):
super(FeesCreationForm, self).__init__(*args, **kwargs)
self.fields['did'].queryset = DepartmentData.objects.none()
# Get did queryset for the selected fid
if 'fid' in self.data:
try:
fd = int(self.data.get('fid'))
self.fields['did'].queryset = DepartmentData.objects.filter(fid_id=fd).order_by('id')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and use empty queryset
elif self.instance.pk:
self.fields['did'].queryset = self.instance.fid.departmentdata_set.order_by('id')
#backward relation - for this faculty selected, check its deparm
#every department has its faculty
# #in other word, which dept has their foreign key pointing to the current instance of faculty

django: inlineformset very slow

I have the following models:
class Recipe(models.Model):
....
class Ingredient(models.Model):
....
class RecipePosition(models.Model):
recipe = models.ForeignKey(Recipe,related_name='recipe_positions', on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient,related_name='ingredient_recipeposition',on_delete=models.PROTECT) ....
in my views.py i am trying to create an inlineformset so that i can edit all the Reciposition related to particular Recipe:
def recipe_ingredients_formset_update(request,slug=None):
instance = get_object_or_404(Recipe.objects.prefetch_related('recipe_positions__ingredient'), slug=slug)
RecipeIngredientsFormSet = inlineformset_factory(Recipe,RecipePosition,form=RecipePoistionForm, can_delete=True, extra=5)
if request.method == "POST":
formset = RecipeIngredientsFormSet(request.POST, request.FILES, instance=instance)
helper = RecipePositionCreateFormSetHelper()
if formset.is_valid():
formset.save()
# Do something. Should generally end with a redirect. For example:
messages.success(request, "Successfully Updated", extra_tags='alert')
return HttpResponseRedirect('')
else:
formset = RecipeIngredientsFormSet(instance=instance)
helper = RecipePositionCreateFormSetHelper()
context = {
"instance":instance,
"formset":formset,
"helper":helper,
"url":instance.get_absolute_url_recipe_update_inline_bulk_ingredients()
}
return render(request, 'recipe_recipositions_bulk_edit.html', context)
I searched on net, but not able to understand. I am using Django Debug toolbar.
If i have 56 RecipePosition items for a particular Recipe. it took me 36 seconds to load

Value of form field update in Django 1.6.6 after POST method

I am trying to update a form field after getting a form in the POST method. When I am trying to update the form I am getting following error
Request Method: POST
Django Version: 1.6.6
Exception Type: TypeError
Exception Value:
'SmsPduForm' object does not support item assignment
My Form Code is
class SmsPduForm(forms.Form):
"""
This class generates the SMS PDU form
"""
pduType = (('1','SMS-SUBMIT'), ('2','SMS-DELIVER'))
encoding = (('0','7 BIT'), ('8','UCS2'))
Address = forms.CharField(max_length=20, min_length=5, required=True, label="Target Address",
initial="+917654321")
SMSC = forms.CharField(max_length=13, min_length=5,required=True, label="SMSC Address",
initial="+91244414")
PDUType = forms.ChoiceField(widget=forms.RadioSelect, choices=pduType, required=True,
label="PDU Type", initial=pduType[0])
EncodingType = forms.ChoiceField(widget=forms.RadioSelect, choices=encoding, required=True, label="Encoding Type",
initial=encoding[0])
Text = forms.CharField(widget=forms.Textarea(attrs={'row':6, 'cols':50}),required=True, label="SMS Text",
initial="Hello", max_length=140)
smsPDU = forms.CharField(widget=forms.Textarea(attrs={'row':6, 'cols':50}),required=True, label="SMS PDU",
initial="Hello", max_length=140)
#Meta class of the form
class Meta:
fields = ('Address', 'SMSC', 'PDUType',
'EncodingType', 'Text', 'smsPDU')
My view code is
def smsHandler(request):
context = RequestContext(request)
if request.method == 'POST':
method=""
#Do for post method else do for get method
smsPduForm = SmsPduForm(request.POST)
smsc = smsPduForm['SMSC'].value()
address = smsPduForm['Address'].value()
encodingType = smsPduForm['EncodingType'].value()
pduType = smsPduForm['PDUType'].value()
text = smsPduForm['Text'].value()
smsPdu = smsPduForm['smsPDU'].value()
print(smsc,address,encodingType,pduType,text,smsPdu)
if "Encode" in request.POST:
method = "encode"
smsEncObj = SmsEncoder(encodingType, smsc, pduType, text, address )
smsPdu = smsEncObj.generateSmsSubmitPdu()
#SmsPduForm.clean_smsPDU()
#Here I am updating the form
smsPduForm['smsPDU'] = smsPdu
elif "Decode" in request.POST:
method = "decode"
print("Action need to perform:",method)
contextDic = {'forms':SmsPduForm}
return render_to_response('telecom_utils/smsUtil.html',contextDic,context)
else:
contextDic = {'forms':SmsPduForm}
return render_to_response('telecom_utils/smsUtil.html',contextDic,context)
How can i update the form ? Kindly look into the issue.
You can use the initial property of the field in a form to update the value .
Example :
def smsHandler(request):
# --- your logic
#Here I am updating the form
sms_form = smsPduForm()
sms_form.fields["smsPDU"].initial = smsPdu
# --- next logic

wtforms, ndb and blobstore

I have this model:
class Product(ndb.Model):
title = ndb.StringProperty()
description = ndb.TextProperty()
img = ndb.BlobKeyProperty(indexed=False)
I need a html form that reads the values ​​of fields (title and description) and read the image (from a file field), and keeps the values ​​NDB object, the image in the Blobstore and updates the field BlobKeyProperty correctly.
As I work with wtforms, I tried to do it with a form like the following:
class ProductForm(Form):
title = fields.TextField('Title', [validators.Required(), validators.Length(min=4, max=25)])
description = fields.TextAreaField('Description')
img = fields.FileField('img')
The form shows the file field correctly but in the POST, it does not work because I don't know how to read the file, save the file to Blobstore and update the BlobKeyProperty.
My handler is this:
class ProductHandler(BaseHandler):
def new(self):
if self.request.POST:
data = ProductForm(self.request.POST)
if data.validate():
model = Product()
data.populate_obj(model)
model.put()
self.add_message("Product add!", 'success')
return self.redirect_to("product-list")
else:
self.add_message("Product not add!", 'error')
params = {
'form': ProductForm(),
"kind": "product",
}
return self.render_template('admin/new.html', **params)
Error is Expected str, got u'image.jpg'
If someone can help me, I would appreciate it!
The only solution I found is to use a deprecated low-level API described in https://developers.google.com/appengine/docs/python/blobstore/#Python_Writing_files_to_the_Blobstore
I make a wtform validator for the FileField.
I changed:
img = fields.FileField('img')
To:
img = fields.FileField('img', [create_upload_file])
And I write this validator:
def create_upload_file(form, field):
file_name = files.blobstore.create(mime_type=field.data.type, _blobinfo_uploaded_filename=field.data.filename)
with files.open(file_name, 'a') as f:
f.write(field.data.file.read())
files.finalize(file_name)
blob_key = files.blobstore.get_blob_key(file_name)
field.data = blob_key
The validator create the blob in blobstore, and then it change the field data from FieldStorage to blob_key.
I don't think that is the best solution but it works for now.

Resources