0

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?

10
  • You need to at least show the code you used. Commented Aug 14, 2018 at 12:25
  • are you asking for the code inside views.py? @DanielRoseman Commented Aug 14, 2018 at 12:33
  • do you have a str method in your model?? Commented Aug 14, 2018 at 12:34
  • yes @EsirKings I updated it. Then, too the situation is still the same. Commented Aug 14, 2018 at 12:38
  • 1
    @AishwaryShukla: this is the issue you are currently facing, you add strings and non-strings together. So what is a "foo" + some_device_type supposed to do? Commented Aug 14, 2018 at 12:50

1 Answer 1

2

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/

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.