Grading calculator - permission denied while setting text box

I would like to make a grading calculator which will take the user score input and converts it to set grade via the server module. I tried using the code below but the code could not run.

    @anvil.server.callable
    def num_to_grade(score)
          if score >= 90:
            if score == 100:
              print "A+"
            else:
              print "A"
          elif score <= 80:
              print "B"
          elif score <= 70:
              print "C"
          else:
             print "F"

We’ll need more information -

  • how are you calling the function? Can you post that piece of code
  • when you say it could not run, what happens?

It’s a client permission error even though the code was called from the server
code in the server is now

@anvil.server.callable
def num_to_grade(score_row, grade_row):
      if score_row >= 90:
        if score == 100:
          grade_row = "A+"
        else:
          grade_row = "A"
      elif score_row <= 80:
          grade_row = "B"
      elif score_row <= 70:
          grade_row = "C"
      else:
         grade_row = "F"

whereas the code in the repeating panel is

 def text_box_1_change(self, **event_args):
    """This method is called when the text in this text box is edited"""
    anvil.server.call_s('num_to_grade', self.item, self.text_box_1.text)

The error obtained is:

anvil.server.InternalError:
Permission denied: Cannot write in table ‘Grades’ from client code.
while setting self.item[‘score’] = self.text_box_1.text
in a data binding for self.text_box_1

Would you be able to share your project (click the gear icon in the project manager, select share app from the drop down menu and copy/paste the “share your source code and data with others” link?

You can PM me if you’d prefer, but without seeing the rest of it it’s hard to know what’s happening.

sorry, but how do I send a PM to you? New user here

Top right corner of the forum is a coloured circle with a letter in it - click this and a drop down menu appears. Click the envelope icon top right (second in), then click the “New Message” (left hand side, blue button)

MY address is “@david.wylie

(based on the project you sent me via PM)

Ok, I’m not seeing the error you’re seeing, but there’s a few things I would do.

  1. don’t trap the change event on the text box, just the enter pressed event, otherwise you will be modifying the box you are typing in whilst you are still typing.
  2. you are passing the data table row as “score_row” and the text box’s text property as “grade_row”. When you set “grade_row” in your server function, you are not updating the text box object’s property (ie it’s not a reference you can set like that). Return the value and set the text box accordingly.
  3. You are checking “score_row” as if it were a value. It’s not, it’s an object. You need to either extract the value you want to compare or even better do that before you pass it. You can prove that by printing both parameters in the server function as your first action.
  4. There’s a typo - you reference “class_score” which is missing an “s” on the end.

More to come …

1 Like

It looks like the expression you entered on a data binding for self.text_box contains an assignment, and that assignment tried to write on a table.

The data binding expression should only return a value, no need to assign.

Or maybe you intend to use data binding to write back to the table, and you need to add writing permission to the table.

Also, your logic seems to be wrong: a score of 50 will return B. You should use all >.

1 Like

Hi Shaoying, welcome to the Forum!

In short, there’s a Data Binding somewhere that you can probably just delete, but here’s a longer explanation!

The problem

The problem is not in the main code, but in a Data Binding. The error message says that it’s in ‘a data binding for self.text_box_1’:

anvil.server.InternalError:
Permission denied: Cannot write in table ‘Grades’ from client code.
while setting self.item[‘score’] = self.text_box_1.text
in a data binding for self.text_box_1

Somewhere in your app, there’s a TextBox called self.text_box_1 with a Data Binding like this:

image

(This Data Bindings panel can be found in the Propoerties pane when you select the TextBox.)

I expect you have a Form called ItemTemplate1, which is the template of a RepeatingPanel. In that case, I guess the RepeatingPanel’s items is set like this (probably in Form1):

self.repeating_panel_1.items = app_tables.grades.search()

So inside the ItemTemplate Form, self.item is a row from the grades table.

The error comes because the Data Binding has the Write back box checked. That means it will try to write self.text_box_1.text into self.item['score'], and because self.item is a Row from the grades table, it does not have permission to do this.

How to fix it

The easiest way

The easiest way is to make the grades table client-writable. Go to the Data Tables Service and select ‘Can search, edit and delete’ for the grades table:

image

The most secure way

This is not ideal in terms of security though - anybody who uses your app can manipulate the code in their browser to read and write to the grades table however they want.

The more secure way is to remove the Data Binding. You can get the same result by writing a function in a Server Module write to the grades table, then call it from the change event of text_box_1. That way, the grades table can still be ‘No access’ from the client, and your server function controls what gets written to it.

It sounds like that’s what you’re trying to do - you want to call num_to_grade from text_box_1_change, so the Data Binding is no longer required.

1 Like

A post was split to a new topic: Permission denied error