Django - POST request not retrieved correctly - django

I'm working on a inventory control in Django and i want a form to control the action that will be made. If a record for the product already exist, it should update the quantity. If it doesn't exist, it should create the record for it. Besides that, one form field will have three choices. One will add the form value to que product quantity, other will subtract and another one will change to the value in the form.
The model is quite big, because i set some choices for the form fields. There it is:
from django.db import models
from django import forms
from django.forms import ModelForm
class Produto(models.Model):
CAMISA = "CM"
QUADRO = "QD"
CANECA = 'CN'
ESCOLHAS_PRODUTO = (
(CAMISA, 'Camisa'),
(QUADRO, 'Quadro'),
(CANECA, 'Caneca'),
)
tipo = models.CharField(max_length = 40,
choices=ESCOLHAS_PRODUTO,
default=CAMISA)
class Camisa(Produto):
MASCULINA = 'MA'
FEMININA_BASICA = 'FB'
FEMININA_GOLA_V = 'FV'
INFANTIL = 'IN'
MODELO_CAMISA = (
(MASCULINA, 'Masculina'),
(FEMININA_BASICA, 'Feminina Basica'),
(FEMININA_GOLA_V, 'Feminina Gola V'),
(INFANTIL, 'Infantil'),
)
modelo = models.CharField(max_length = 50,
choices=MODELO_CAMISA,
)
AMARELA = 'AM'
AZUL_CLARO = 'AC'
AZUL_ESCURO = 'AE'
BRANCA = 'BR'
CINZA = 'CI'
LARANJA = 'LA'
MARFIM = 'MA'
ROSA = 'RO'
PRETA = 'PR'
VERDE_MUSGO = 'VM'
VERMELHA = 'VR'
CORES_CAMISA = (
(AMARELA, 'Amarela'),
(AZUL_CLARO, 'Azul Claro'),
(AZUL_ESCURO, 'Azul Escuro'),
(BRANCA, 'Branca'),
(CINZA, 'Cinza'),
(LARANJA, 'Laranja'),
(MARFIM, 'Marfim'),
(ROSA, 'Rosa'),
(PRETA, 'Preta'),
(VERDE_MUSGO, 'Verde Musgo'),
(VERMELHA, 'Vermelha'),
)
cor = models.CharField(max_length = 40,
choices=CORES_CAMISA,
)
TAMANHO_P = 'TP'
TAMANHO_M = 'TM'
TAMANHO_G = 'TG'
TAMANHO_GG = 'GG'
TAMANHO_XG = 'XG'
TAMANHO_02_ANOS = '02'
TAMANHO_04_ANOS = '04'
TAMANHO_06_ANOS = '06'
TAMANHO_08_ANOS = '08'
TAMANHO_10_ANOS = '10'
TAMANHO_12_ANOS = '12'
TAMANHO_14_ANOS = '14'
TAMANHO_CAMISA = (
(TAMANHO_P, 'P'),
(TAMANHO_M, 'M'),
(TAMANHO_G, 'G'),
(TAMANHO_GG, 'GG'),
(TAMANHO_XG, 'XGG'),
(TAMANHO_02_ANOS, '2 Anos'),
(TAMANHO_04_ANOS, '4 Anos'),
(TAMANHO_06_ANOS, '6 Anos'),
(TAMANHO_08_ANOS, '8 Anos'),
(TAMANHO_10_ANOS, '10 Anos'),
(TAMANHO_12_ANOS, '12 Anos'),
(TAMANHO_14_ANOS, '14 Anos'),
)
tamanho= models.CharField(max_length = 50,
choices=TAMANHO_CAMISA,
)
quantidade = models.IntegerField()
def __unicode__(self):
return self.modelo
class CamisaForm(ModelForm):
ADICIONAR = 'ADC'
REDUZIR = 'RED'
ALTERAR = 'ALT'
ACOES = (
(ADICIONAR, 'Adicionar Quantidade'),
(REDUZIR, 'Reduzir Quantidade'),
(ALTERAR, 'Alterar para Quantidade'),
)
acoes = forms.ChoiceField(
choices=ACOES,
)
class Meta:
model = Camisa
And the following view:
def index(request):
produtos_estoque = Camisa.objects.all()
template = 'estoque/index.html'
modelos_camisa = {'MA' : 'Masculina Basica','FB' : 'Feminina Basica','FV' : 'Feminina Gola V','IN' : 'Infantil' }
if request.method == 'POST':
form = CamisaForm(request.POST)
if form.is_valid():
try:
produto_atualizar = Camisa.objects.get(modelo = request.POST['modelo'], cor = request.POST['cor'], tamanho = request.POST['tamanho'])
if request.POST['acoes'] == 'ADC':
produto_atualizar.quantidade = produto_atualizar.quantidade + request.POST['quantidade']
elif request.POST['acoes'] == 'RED':
produto_atualizar.quantidade = produto_atualizar.quantidade - request.POST['quantidade']
elif request.POST['acoes'] == 'ALT':
produto_atualizar.quantidade = request.POST['quantidade']
produto_atualizar.save()
except:
produto_atualizar = form.save()
return HttpResponseRedirect('')
else:
form = CamisaForm()
return render_to_response(template, { 'form': form, 'produtos_estoque': produtos_estoque,
'modelos_camisa' : modelos_camisa.iteritems(), }, context_instance=RequestContext(request))
But what is happening is that the form is just creating another record for the product, even if it already exists. Not sure if the rest of the model is important for this question, will post it if necessary. Can somebody help me on this one? Thanks

Please post the Model this is acting on - it will have some useful information, like constraints or lack thereof etc. OK cool, no unique constraints in there causing insert violations.
First thing I would recommend is using the forms cleaned_data to access form values instead of the raw POST data, form.is_valid() does a lot of work to process the raw data into acceptable inputs for Model data.
Second thing is that except clause will catch ANY exception which I suspect is your problem... Something else is going wrong which is creating the new record in the except clause. Be specific, like except Camisa.DoesNotExist:
Third thing is to put those constants on the Model so you can reference them from the Form and View instead of literal strings. This is just a cleanliness / code style recommendation.
A little cleanup might look like:
MODELOS_CAMISA = {'MA' : 'Masculina Basica','FB' : 'Feminina Basica','FV' : 'Feminina Gola V','IN' : 'Infantil' }
def index(request):
produtos_estoque = Camisa.objects.all()
if request.method == 'POST':
form = CamisaForm(request.POST)
if form.is_valid():
try:
produto_atualizar = Camisa.objects.get(modelo=form.cleaned_data.get('modelo'), cor=form.cleaned_data.get('cor'), tamanho=form.cleaned_data.get('tamanho'))
quantidade = form.cleaned_data.get('quantidade')
acoes = form.cleaned_data.get('acoes')
if acoes == Camisa.ADC:
produto_atualizar.quantidade = produto_atualizar.quantidade + quantidade
elif acoes == Camisa.RED:
produto_atualizar.quantidade = produto_atualizar.quantidade - quantidade
elif acoes == Camisa.ALT:
produto_atualizar.quantidade = quantidade
produto_atualizar.save()
except Camisa.DoesNotExist:
produto_atualizar = form.save()
return HttpResponseRedirect('')
else:
form = CamisaForm()
return render_to_response('estoque/index.html', { 'form': form, 'produtos_estoque': produtos_estoque,
'modelos_camisa' : MODELOS_CAMISA.iteritems(), }, context_instance=RequestContext(request))
(Sorry for any grammatical errors, my Portuguese is not great)
That should be enough to get you started, if you add more information I can edit and elaborate my answer. Good luck!

Related

Update set of fields in django model passed in request.POST

This is my Model class
class SubJobs(models.Model):
id = models.AutoField(primary_key = True)
subjob_name = models.CharField(max_length=32,help_text="Enter subjob name")
subjobtype = models.ForeignKey(SubjobType)
jobstatus = models.ForeignKey(JobStatus, default= None, null=True)
rerun = models.ForeignKey(ReRun,help_text="Rerun")
transfer_method = models.ForeignKey(TransferMethod,help_text="Select transfer method")
priority = models.ForeignKey(Priority,help_text="Select priority")
suitefiles = models.ForeignKey(SuiteFiles,help_text="Suite file",default=None,null=True)
topofiles = models.ForeignKey(TopoFiles,help_text="Topo file",default=None,null=True)
load_image = models.NullBooleanField(default = True,help_text="Load image")
description = models.TextField(help_text="Enter description",null=True) command = models.TextField(help_text="Command",null=True)
run_id = models.IntegerField(help_text="run_id",null=True)
pid_of_run = models.IntegerField(help_text="pid_of_run",null=True)
hold_time = models.IntegerField()
created = models.DateTimeField(default=timezone.now,null=True)
updated = models.DateTimeField(default=timezone.now,null=True)
finished = models.DateTimeField(null=True)
The user might want to update a entry and may choose to update only few fields among these. How do I write a generic update statement that would update only the fields that were passed?
I tried this.
def update_subjob(request):
if (request.method == 'POST'):
subjobs_subjobid = request.POST[('subjob_id')]
post_data = request.POST
if 'subjob_name' in post_data:
subjobs_subjobname = request.POST[('subjob_name')]
if 'subjob_type' in post_data:
subjobs_subjobtype = request.POST[('subjob_type')]
if 'rerun_id' in post_data:
subjobs_rerun_id = request.POST[('rerun_id')]
if 'priority_id' in post_data:
subjobs_priority_id = request.POST[('priority_id')]
if 'transfer_method' in post_data:
subjobs_transfermethod = request.POST[('transfer_method')]
if 'suitefile' in post_data:
subjob_suitefile = request.POST[('suitefile')]
if 'topofile' in post_data:
subjob_topofile = request.POST[('topofile')]
try:
subjobinstance = SubJobs.objects.filter(id=subjobs_subjobid).update(subjob_name=subjobs_subjobname,
updated=datetime.now())
except Exception as e:
print("PROBLEM UPDAING SubJob!!!!")
print(e.message)
How do I write a generic update to update only those fields which are sent in request.POST?
You'd better use Forms. But if you insist on your code it could be done like this.
Suppose you have variable field_to_update where every field that you are waiting in request is listed.
subjobs_subjobid = request.POST[('subjob_id')]
field_to_update = ('subjob_name','subjob_type', 'rerun_id', 'priority_id', 'transfer_method', 'suitefile', 'topofile')
post_data = request.POST
to_be_updated = {field: post_data.get(field) for field in field_to_update if field in post_data}
# then you need to get the object, not filter it
try:
subjobinstance = SubJobs.objects.get(id=subjobs_subjobid)
subjobinstance.update(**to_be_updated, updated=datetime.now())
except ObjectDoesNotExist: # from django.core.exceptions
print('There is no such object') # better to use logger
except Exception as e:
print("PROBLEM UPDAING SubJob!!!!")
print(e.message)

Django form won't bind to POST data

I am really struggling trying to get my POST data to bind to this form. POST data is coming through properly and appears to be in the right form, but it absolutely refuses to bind to the form for validation. I'm new to this so I'm sure I'm missing something obvious, but any help figuring out why this is happening would be greatly appreciated.
views.py
def new_call(request):
if not request.user.is_authenticated():
return redirect(login_view)
if request.method == "POST":
form = RegisterCallForm(request.POST,user=request.user)
#Prints False
print form.is_bound
if form.is_valid():
answered = form.cleaned_data['answered']
left_message = form.cleaned_data['left_message']
contact_pk = form.cleaned_data['contact']
time_called = form.cleaned_data['time_called']
note = form.cleaned_data['note']
staff_person = request.user.userprofile
call = Call(
staff_person=staff_person,
contact=contact,
answered=answered,
left_message=left_message,
time=time_called,
note=note,
)
call.save()
if request.POST.get('submit') == 'continue':
return redirect(user_profile_view)
else:
return redirect(new_call)
else:
form = RegisterCallForm(user=request.user,)
return render(request, 'supporttracker/register_call.html',{'form':form})
And here's the form...
forms.py
class RegisterCallForm(forms.Form):
def __init__(self,*args,**kwargs):
self.user = kwargs.pop('user',User)
super (RegisterCallForm, self).__init__(*args,**kwargs)
self.fields['contact'] = forms.TypedChoiceField(
choices = get_contact_list(self.user),
label = 'Call with',
)
new_fields = OrderedDict()
new_fields['contact'] = self.fields['contact']
new_fields['answered'] = self.fields['answered']
new_fields['left_message'] = self.fields['left_message']
new_fields['time_called'] = self.fields['time_called']
new_fields['note'] = self.fields['note']
self.fields = new_fields
answered = forms.TypedChoiceField(
label='Answered:',
coerce=lambda x: x == 'Yes',
choices=((False, 'No'), (True, 'Yes')),
widget=forms.RadioSelect
)
left_message = forms.TypedChoiceField(
label='Left a message:',
coerce=lambda x: x == 'Yes',
choices=((False, 'No'), (True, 'Yes')),
widget=forms.RadioSelect
)
time_called = forms.DateTimeField(
label = 'Time of call',
initial = datetime.datetime.now,
required = False,
)
note = forms.CharField(
max_length=500,
widget=forms.Textarea,
required=False,
)
It seems you forget to call super init. How do you expect form class do it's normal job when you override the init function?

IntegrityError error while saving value of to foreign key in django

Hey folks i am getting integrity error while saving my views .Please tell me what i am doing wrong
Here is my django model
class Ruleinfo(models.Model):
rule = models.IntegerField(null=False)
From = models.IPAddressField(null=True)
to = models.IPAddressField(null=True)
priority = models.ForeignKey('Priority',related_name='pri_no')
cisp =models.ForeignKey('Priority',related_name = 'CISP_no')
def __unicode__(self):
return u'%s' %(self.rule)
class Priority(models.Model):
pri = models.IntegerField(null = True)
Ruleno = models.ForeignKey('Ruleinfo',related_name = 'ruleno_no')
CISP = models.IntegerField(null = True)
def __unicode__(self):
return u'%s ' % (self.priority)
My model form is looking like .
class RuleInfoForm(ModelForm):
class Meta:
model = Ruleinfo
fields = ("rule","From","to")
here is my views.py
def multiwanrule_info(request):
data = {}
no_of_isp = MultiWAN.objects.all()
try:
form = RuleInfoForm(request.POST)
except:
pass
print "----------------------------printing form"
print form
if form.is_valid():
rl_frm = form.save(commit=False)
get_priorities = request.POST.getlist('priority')
get_cisp_info = request.POST.getlist('cisp')
rule_object = Ruleinfo()
for get_pri,get_ci in zip(get_priorities,get_cisp_info,):
pri_object = Priority.objects.get_or_create(Ruleno = rule_object)
pri_object.pri = get_pri
pri_object.CISP = get_ci
rl_frm.save()
else:
form = RuleInfoForm()
data['form'] = form
data['number_of_isp'] = no_of_isp
return render_to_response('networking.html',data)
I am getting the above error along this
networking_priority.Ruleno_id may not be NULL
help me out so that i could get back on track .
rule_object = Ruleinfo()
This just instantiates a new model object. It is not saved or assigned values. Since it is not saved it does not have an id value.
assigning your rule_object values: rule, from, to, priority, and cisp values, should fix your problem.

Creating different completion paths using form wizard - Django

I was following the tutorial online, but I am stuck when trying to conditionally show steps in my form wizard.
views.py
def silver_ad_selected(wizard):
cleaned_data = wizard.get_cleaned_data_for_step('0') or {}
return cleaned_data.get('ad_type') == '2'
def platinum_ad_selected(wizard):
cleaned_data = wizard.get_cleaned_data_for_step('0') or {}
return cleaned_data.get('ad_type') == '3'
class AddWizard(SessionWizardView):
def done(self, form_list, **kwargs):
return render_to_response('business/done.html', {
'form_data': [form.cleaned_data for form in form_list],
})
urls.py:
add_forms = [AddForm1, AddForm2, AddForm3]
urlpatterns = patterns('listings.views',
url(r'^addWizard/$', AddWizard.as_view(add_forms,
condition_dict = {
'2': silver_ad_selected or premium_ad_selected
})),
.......
forms.py
class AddForm1(forms.Form):
TYPE_CHOICES = (
('1','Basic'),
('2','Silver'),
('3','Platinum')
)
ad_type = forms.ChoiceField(choices=TYPE_CHOICES, widget=forms.RadioSelect)
class AddForm2(forms.Form):
category = forms.ModelChoiceField(queryset = Category.objects.all())
city = forms.ModelChoiceField(queryset = City.objects.all())
name = forms.CharField(max_length = 200)
address = forms.CharField(max_length = 200)
slogan = forms.CharField(max_length=140)
phone = forms.CharField(max_length=10)
website = forms.URLField()
email = forms.EmailField()
class AddForm3(AddForm2):
twitter = forms.CharField(max_length=100)
facebook = forms.URLField()
description = forms.CharField(widget=forms.Textarea)
Basically, I only want to show the last step if the user chooses either the "Silver" option or the "Platinum" option, which is selected in step 1. Right now, no matter what I choose, only the first two steps/forms are shown.
I think that my silver_ad_selected and platinum_ad_selected methods might be the problem, but I am not sure.
Thanks
Try changing your urls.py:
add_forms = [AddForm1, AddForm2, AddForm3]
urlpatterns = patterns('listings.views',
url(r'^addWizard/$', AddWizard.as_view(add_forms,
condition_dict = {
'2': lambda wizard: wizard.silver_ad_selected() or wizard.premium_ad_selected()
})),

inlineformset_factory composed of ModelForm

Is it possible for an inlineformset_factory to take in a ModelForm as well as a model. When I try to run this I get an error message 'NoneType' object is not iterable.
Please help, I've spent an entire day trying to figure this out. Thanks.
Code:
Model.py
class FilterForm(ModelForm):
firstFilter = forms.BooleanField(label='First Filter', initial=False, required=False)
class Meta:
model = Filter
exclude = ('order')
class Controller(models.Model):
protocol = models.CharField('Protocol',max_length=64, choices=PROTOCOLS, default='http')
server = models.CharField('Server', max_length=64, choices=SERVERS, default='127.0.0.1')
name = models.CharField('Name', max_length=64)
def __unicode__(self):
return self.protocol + '://' + self.server + '/' + self.name
view.py
def controller_details(request, object_id):
controller = Controller.objects.get(pk=object_id)
controllerURI = controller.protocol + '://' + controller.server + '/' + controller.name
FilterFormSet = inlineformset_factory(Controller, FilterForm, extra=5)
if request.method == 'POST':
formset = FilterFormSet(request.POST, request.FILES, instance=controller)
if formset.is_valid():
filters = []
# Save all the filters into a list
forms = formset.cleaned_data
for form in forms:
if form:
protocol = form['protocol']
server = form['server']
name = form['name']
targetURI = form['targetURI']
filterType = form['filterType']
firstFilter = form['firstFilter']
if firstFilter == True:
aFilter = Filter(controller=controller, protocol=protocol, server=server, name=name, targetURI=targetURI, filterType=filterType, order=0)
else:
aFilter = Filter(controller=controller, protocol=protocol, server=server, name=name, targetURI=targetURI, filterType=filterType, order=-1)
filters.append(aFilter)
# Find the first filter in the list of filters
for index, aFilter in enumerate(filters):
if aFilter.order == 0:
break
if filters[index].targetURI:
test = "yes"
else:
for aFilter in filters:
aFilter.save()
else:
formset = FilterFormSet(instance=controller)
return render_to_response('controller_details.html', {'formset':formset, 'controllerURI':controllerURI}, context_instance=RequestContext(request))
UPDATE: If you intended to create a FormSet with Controller and Filter models where Filter holds a FK to the Controller, you need:
FilterFormSet = inlineformset_factory(Controller, Filter, form=FilterForm)
Note that in your code above, you're only passing the the Controller model class, which caused some confusion.