Django form not inserting form values - python

I have a from created which is generated by a model. I can save the form, but the form data is not inserted into the table. The insert occurs, but with blank data. Any help would be greatly appreciated.
models.py
class HelpDefinition(models.Model):
org = models.IntegerField(default=0)
help_type = models.CharField(max_length=255)
help_content = models.TextField(blank=True)
def __unicode__(self):
return self.name
views.py
def index(request, org_id=None):
help_def = HelpDefinition()
if org_id:
help_def = HelpDefinition.objects.get(org=org_id)
if request.method == 'POST':
form = FormHelp(request.POST)
if form.is_valid():
help_def.save()
messages.success(request, 'Saved!')
else:
messages.error(request, 'Ugh')
else:
form = FormHelp(request=request, initial=initial_data)
return {
'form': form,
}
forms.py
class FormHelp(forms.Form):
org = forms.CharField(widget=forms.HiddenInput, required=True)
help_type = forms.ChoiceField(abel='Text', required=True)
help_content = forms.CharField(label='Description', required=True, widget=forms.Textarea)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(FormHelp, self).__init__(*args, **kwargs)

Due that you dont use ModelForm, you need to set your attributes one by one.
if request.method == 'POST':
form = FormHelp(request.POST)
if form.is_valid():
help_def.org = form.cleaned_data.get("org")
help_def.help_type = form.cleaned_data.get("help_type")
help_def.help_type = form.cleaned_data.get("help_content")
help_def.save()

Related

Django - NOT NULL constraint failed

I'm currently working on a Django app that will parse the contents of an uploaded log file to the associated database in my Django project. I've managed to get it all running as expected except it won't associate my uploaded data with the model's ForeignKey. I can assign null=True which resolves the integrity error but then of course, it doesn't assign any of the uploaded data to that ForeignKey. Here's the code:
models.py
class Case(models.Model):
case_ref = models.CharField(max_length=8)
oic = models.CharField(max_length=50)
subject = models.CharField(max_length=100)
submitted_date = models.DateTimeField(default=datetime.now, blank=True)
def get_absolute_url(self):
return reverse('case_list', kwargs={'pk': self.pk})
def __str__(self):
return self.case_ref + " " + self.subject
class TeamviewerLogs(models.Model):
case = models.ForeignKey(Case, on_delete=models.DO_NOTHING)
teamviewer_id = models.IntegerField()
teamviewer_name = models.TextField()
connection_start = models.TextField()
connection_end = models.TextField()
local_user = models.TextField()
connection_type = models.TextField()
unique_id = models.TextField()
def get_absolute_url(self):
return reverse('case_list', kwargs={'pk': self.pk})
def __str__(self):
return str(self.teamviewer_id) + " - " + str(self.teamviewer_id)
forms.py
class UploadLog(forms.ModelForm):
file = forms.FileField()
class Meta:
model = TeamviewerLogs
fields = [
'file'
]
views.py
def add_logs(request, pk):
case = get_object_or_404(Case, pk=pk)
if request.method == 'POST':
form = UploadLog(request.POST, request.FILES)
if form.is_valid():
teamviewer = form.save(commit=False)
teamviewer.case = case
log_file = request.FILES['file']
log_file = filter(None, (line.rstrip() for line in log_file))
for lines in log_file:
split = lines.decode('utf-8').split('\t')
teamviewer_id = split[0]
teamviewer_name = split[1]
connection_start = split[2]
connection_end = split[3]
local_user = split[4]
connection_type = split[5]
unique_id = split[6]
teamviewer = TeamviewerLogs(teamviewer_id=teamviewer_id, teamviewer_name=teamviewer_name,
connection_start=connection_start, connection_end=connection_end,
local_user=local_user, connection_type=connection_type, unique_id=unique_id)
teamviewer.save()
return redirect('tv_log_details', pk=case.pk)
form.save()
else:
form = UploadLog()
return render(request, 'teamviewer/add_logs.html', {'form': form})
But when I click to upload the file I'm hit with:
When it tries to execute teamviewer.save().
I've been trying to resolve this issue for hours and have tried so many different variations of answers from Stackoverflow or previous code I've used that has worked for different models but I've hit a brick wall...hard!
Any help anyone can offer would be greatly appreciated.
Ok, so here's an example of the concept I've suggested in the comments.
I've got a view which passes some data to the a form;
class ListingDetailView(DetailView):
""" Listing detail page """
model = Listing
template_name = 'listing.html'
def get_form_kwargs(self):
"""Return the kwargs for the form"""
kwargs = {}
initial = {
'listing': self.object,
}
kwargs['initial'] = initial
return kwargs
def get_form(self):
form = ApplicationSignupForm(
**self.get_form_kwargs()
)
return form
def get_context_data(self, **kwargs):
""" Add our form to the context """
context = super().get_context_data(**kwargs)
context['form'] = self.get_form()
return context
The form then makes use of that initial data and sets the field it relates to as hidden. I don't validate this data, but I'll try to show how you might do that;
class ApplicationSignupForm(forms.ModelForm):
class Meta:
""" Setup the form """
fields = (
'listing',
...
)
model = Application
widgets = {
'listing': forms.HiddenInput()
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
initial_data = kwargs['initial']
self.listing = initial_data.get('listing')
def clean(self):
"""
Custom form cleaning
"""
cleaned_data = super().clean()
listing = cleaned_data.get('listing')
if listing != self.listing:
self.add_error('listing', "You can't modify this value")
return cleaned_data

Want to have Django From dropdown filtered by logged-in User (Customer), using __init__ method

Want to have Django From dropdown filtered by logged-in User (Customer), using __init__ method. But when submit the form, keep having this Field id expected a number but got <QueryDict: { error:
class OrderForm(ModelForm):
class Meta:
model = Order
fields = ['contract', 'quantity', 'status']
def __init__(self, customer, *args, **kwargs):
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['contract'].queryset = Contract.objects.filter(customer=customer)
#login_required(login_url='login')
def createOrder(request):
customer = request.user.customer.id
form = OrderForm(customer)
if request.method == 'POST':
form = OrderForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.customer = request.user.customer
form.save()
messages.success(request, 'Ticket submitted successfully .')
return redirect('customer_table')
context = {'form':form}
return render(request, 'create-order.html', context)
you can pass any attribute in form like this
in view:
form = OrderForm(request.POST, customer=request.user)
in form:
def __init__(self, *args, **kwargs):
customer = kwargs.pop('user') # allway before super()
# and call .pop() not .get() on kwargs, for upper class not evaluate user keyword
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['contract'].queryset = Contract.objects.filter(customer=customer)
I summarize the working solutions as below:
View.py
def createOrder(request):
form = OrderForm(request.POST, customer=request.user.customer.id)
if request.method == 'POST':
form = OrderForm(request.POST, customer=request.user.customer.id)
if form.is_valid():
form = form.save(commit=False)
form.customer = request.user.customer
form.save()
messages.success(request, 'Ticket submitted successfully .')
return redirect('customer_table')
context = {'form':form}
return render(request, 'create-order.html', context)
class OrderForm(ModelForm):
class Meta:
model = Order
fields = ['contract', 'quantity', 'status']
def __init__(self, *args, **kwargs):
customer = kwargs.pop('customer')
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['contract'].queryset = Contract.objects.filter(customer__id=customer)

Field 'id' expected a number but got <QueryDict: >error in django

I have this form:
class addMeal(forms.Form):
name = forms.CharField(
max_length=40,
widget=forms.TextInput(attrs={'class':'form-control','placeholder':'نام وعده'})
)
foods = forms.ModelMultipleChoiceField(
queryset=Food.objects.none(),
widget=forms.SelectMultiple(attrs={'class':'form-control'})
)
def save(self,request):
data = self.cleaned_data
meal = Meals(name=data['name'],user=request.user,foods=data['foods'])
meal.save()
def __init__(self, user=None,*args, **kwargs, ):
super().__init__(*args, **kwargs)
if user is not None:
self.fields['foods'].queryset = Food.objects.filter(user=user)
class Meta:
model = Meals
and this view:
#login_required
def addmeal(request):
if request.method == 'POST':
form = addMeal(request.POST)
if form.is_valid():
form.save(request)
return redirect('food:index')
else:
form = addMeal(user=request.user)
return render(request,'addmeal.html',{'form':form})
when i fill out form and press submit django give me error(Field 'id' expected a number but got <QueryDict: {'csrfmiddlewaretoken': ['C2B8y3kLCa5IQ0S5Mvk7Tw0NTU4pNlYicppWlsIL1LCrcc8AuCQzjJkqWNUot4z6'], 'name': ['شام'], 'foods': ['1']}>.).
what should i do to fix it?
Since user is the first parameter, you pass the data as second, so:
#login_required
def addmeal(request):
if request.method == 'POST':
form = addMeal(user=request.user, data=request.POST)
if form.is_valid():
form.save(request)
return redirect('food:index')
else:
form = addMeal(user=request.user)
return render(request,'addmeal.html',{'form':form})

form.is_valid() is false why?

I want to store a POST request to a database, so I a had model form MessageForm and called it from views to validate the data and save it.
models.py
class phoneNumber(models.Model):
address = models.CharField(max_length=15)
def __str__(self):
return self.address
class Message(models.Model):
to = models.ForeignKey(phoneNumber, null=True)
sentfrom = models.CharField(max_length=15, null=True)
content = models.TextField(null=True)
def __str__(self):
return '%s' % (self.content)
forms.py
class MessageForm(forms.ModelForm):
class Meta:
model = Message
fields = '__all__'
def __init__(self, *args, **kwargs):
to = kwargs.pop('to', '')
super(MessageForm, self).__init__(*args, **kwargs)
self.fields['to']=forms.ModelChoiceField(queryset=phoneNumber.objects.filter(address=to))
views.py
#csrf_exempt
def incoming(request):
if request.method == "POST":
form = MessageForm(request.POST)
if form.is_valid():
twiml = '<Response><Message>Yes</Message></Response>'
else:
twiml = '<Response><Message>No</Message></Response>'
else:
twiml = '<Response><Message></Message></Response>'
return HttpResponse(twiml, content_type='text/xml')
Nothing is saved and I get No response when I test it.
You can access your errors in views.py
#csrf_exempt
def incoming(request):
if request.method == "POST":
form = MessageForm(request.POST)
if form.is_valid():
twiml = '<Response><Message>Yes</Message></Response>'
else:
print(form.errors)
print(form.non_field_errors)
twiml = '<Response><Message>No</Message></Response>'
else:
twiml = '<Response><Message></Message></Response>'
return HttpResponse(twiml, content_type='text/xml')
Have you tried:
def __init__(self, *args, **kwargs):
to = kwargs.pop('to', '')
super(MessageForm, self).__init__(*args, **kwargs)
self.fields['to'].queryset = phoneNumber.objects.filter(address=to)
Also I'm not sure if you want to pass anything to the form in views method, because right now your to in form is empty string, so your queryset is querying on phoneNumber.objects.filter(address=''), which may or may not be what you want.
Edit:
The reason that to is empty string because kwargs.pop('to', '') means "pop argument to out from kwargs, if to is not there the default is ''". In your views you do:
form = MessageForm(request.POST)
but you didn't feed the constructor with any to argument, so kwargs.pop('to', '') would get '' as default value. You might need something like:
form = MessageForm(request.POST, to="white house")

Django: Setting values of certain attributes in the database using views?

I have a form in my application which has a hidden form field, the value of which I want to set in my corresponding view after submitting the form.
forms.py
class EvangelizedForm(forms.ModelForm):
first_name = forms.CharField(help_text="First Name")
last_name = forms.CharField(help_text="Last Name")
email = forms.CharField(help_text="Email ID")
mobile_no = forms.CharField(help_text="Mobile number")
twitter_url = forms.CharField(help_text="Twitter URL")
twitter_followers = forms.CharField(widget = forms.HiddenInput()) #Hidden form field
class Meta:
model = Evangelized
fields = ('first_name','last_name', 'twitter_url', 'email', 'mobile_no')
models.py
class Evangelized(models.Model):
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
email = models.EmailField()
mobile_no = models.CharField(unique=True, max_length = 10, validators=[RegexValidator(regex='^\w{10}$', message='Mobile number should be strictly of 10 digits.')])
twitter_url = models.CharField(unique=True, max_length=128)
twitter_followers = models.CharField(max_length = 128)
views.py
def fillform(request):
follower_count = '250'
if request.method == 'POST':
form = EvangelizedForm(request.POST)
if form.is_valid():
form.fields['twitter_followers'] = follower_count
form.save(commit=True)
return index(request)
else:
form.errors
else:
#form = EvangelizedForm()
if request.user.is_authenticated():
form = EvangelizedForm(initial={'first_name': request.user.first_name,
'twitter_url': 'https://twitter.com/' + request.user.username,
'last_name': request.user.last_name})
else:
form = EvangelizedForm()
context = RequestContext(request,
{'request': request,
'user': request.user, 'form':form})
#return render(request, 'rango/fillform.html', {'form': form, 'context_instance':context})
return render_to_response('rango/fillform.html',
context_instance=context)
Basically, I'm trying to set the value of twitter_followers (which is a hidden form field in forms.py) in my index view, by:
follower_count = '250'
..
..
form.fields['twitter_followers'] = follower_count
By doing this, I'm expecting the value of 'twitter_followers' in the database after submitting the form to be '250'. However, this approach doesn't seem to be working.
What's the right way to set values to certain attributes in the database manually using views?
You need to set it on the model instance, which is the result of form.save. That's the main reason for the commit argument in the first place.
if form.is_valid()
obj = form.save(commit=True)
obj.twitter_follower = follower_count
obj.save()
You can override the save method of the form, with something like this:
def save(self, *args, **kwargs)
twitter_followers = kwargs.pop('twitter_followers', 0)
self.instance.twitter_followers = twitter_followers
super(Evangelized, self).save(args, kwargs)
And then in the view just have to call in this way:
form.save(twitter_followers=250)

Categories