Reputation: 460
Following is a snapshot of one of my models in django application:
class Request(models.Model):
device_type = models.ForeignKey(DeviceType,to_field='device_type')
requested_by = models.ForeignKey(User,to_field='username')
urgency = models.ForeignKey(RequestUrgency,to_field='request_urgency')
request_must_be_satisfied_by = models.DateField(null=True)
reason = models.TextField()
status = models.ForeignKey(ResuestStatus,to_field='request_status',default="PENDING")
request_date = models.DateField(default=datetime.now)
def __unicode__(self):
return self.device_type
def __str__(self):
return self.device_type
Code inside the views.py file:
def request_form(request):
if request.method == "POST":
print("Inside out if")
form = RequestForm(request.POST)
print("request form: ", form)
print("request fields ", form.fields)
print("errors: ",form.errors.as_data())
if form.is_valid():
print("errors: ",form.errors.as_data())
if form.is_valid():
cleaned_data = form.cleaned_data
post = form.save(commit = False)
post.requested_by_id = request.user
post.save()
userdata = User.objects.get(username = request.user.username)
useremail = userdata.email
email_body_text = "Hi "+request.user.username+","+"\n"+"Your requested a repair for the following:"+"\n"\
+"Device Type: "+cleaned_data["device_type"]+"\n"\
+"Urgency: "+cleaned_data["urgency"]+"\n"\
+"Request must be satisfied by: "+cleaned_data["request_must_be_satisfied_by"]+"\n"\
+"Reason for new device: "+cleaned_data["reason"]+"\n"\
+"We will try to complete your request at the earliest. In case of any concerns contact the controller of operations."
send_mail(email_subject,email_body_text,config.sender_email_id,[useremail],fail_silently=False)
return redirect("NewRequest")
else:
print("Inside else")
form = RequestForm(initial={'requested_by':request.user})
Tp = DeviceType.objects.all()
Tp = Tp.annotate(text=F('device_type')).values_list('text', flat=True)
print("Tp request form: ", Tp)
Ur = RequestUrgency.objects.all()
Ur = Ur.annotate(text=F('request_urgency')).values_list('text', flat=True)
form.fields["device_type"] = forms.ModelChoiceField(queryset=Tp, empty_label=None)
form.fields["urgency"] = forms.ModelChoiceField(queryset=Ur, empty_label=None)
return render(request, "Form_template.html", {"form": form, \
"name": "Device Request Form"})
Now, I have a function in my views.py that validates the data that is submitted through the django rendered form. Now, I have a situation, I want to print the data sent through the form by concatinating it with a particular string. Whenever I got to do so. I get the following error:
TypeError: coercing to Unicode: need string or buffer, DeviceType found
How should I overcome this problem?
Upvotes: 0
Views: 5877
Reputation: 476659
The problem is that you add strings and non-strings together when you construct the email_body_text
. Python does not understand what a string together with a device_type
is supposed to mean. This is not strange, adding a string and a number has the same problems:
>>> u"abc" + 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, int found
As you see, the message is exactly the same, except for the fact that here we use an int
instead of a DeviceType
.
You better solve this by performing string formatting. This is not only more type safe (since it will call unicode(..)
and str(..)
behind the curtains, but is also more elegant.
But there are other problems with the view as well: for example you use cleaned_data
instead of the Request
object you constructed in the form, which make things easier, more elegant and readable:
def request_form(request):
if request.method == "POST":
form = RequestForm(request.POST)
if form.is_valid():
post = form.save(commit = False)
post.requested_by_id = request.user
post.save()
user = request.user
useremail = user.email
email_body_text = (
u"Hi {},"
"\nYour requested a repair for the following:"
"\nDevice Type: {}"
"\nUrgency: {}"
"\nRequest must be satisfied by: {}"
"\nReason for new device: {}"
"\nWe will try to complete your request at the earliest."
"In case of any concerns contact the controller of operations."
).format(
user.username,
post.device_type,
post.urgency,
post.request_must_be_satisfied_by,
post.reason,
)
send_mail(email_subject,email_body_text,config.sender_email_id,[useremail],fail_silently=False)
return redirect("NewRequest")
else:
form = RequestForm(initial={'requested_by':request.user})
Tp = DeviceType.objects.all()
Tp = Tp.annotate(text=F('device_type')).values_list('text', flat=True)
print("Tp request form: ", Tp)
Ur = RequestUrgency.objects.all()
Ur = Ur.annotate(text=F('request_urgency')).values_list('text', flat=True)
form.fields["device_type"] = forms.ModelChoiceField(queryset=Tp, empty_label=None)
form.fields["urgency"] = forms.ModelChoiceField(queryset=Ur, empty_label=None)
return render(request, "Form_template.html", {"form": form, "name": "Device Request Form"})
Note; I advice you to migrate to Python-3.x, since Python-2.x will no longer be supported within two years: https://pythonclock.org/
Upvotes: 2