0

Having trouble finding a totally clear answer to this question. In my learning, I was taught to not pass along the entire request object when trying to pass data from views.py to models.py (when using a django manager).

However, in my current scenario, I'm trying to setup validation methods in my models.py (using a Manager) whereby I utilize django-messages (https://docs.djangoproject.com/en/1.11/ref/contrib/messages/), to whom one requirement is the request object itself when generating custom errors, such as:

messages.add_message(request, REG_ERR, 'First and last name are required must be at least 2 characters.', extra_tags="reg_errors")

I am trying to keep all validations, error message generation, and creation or retrieval actions inside of my models.py using a manager (https://docs.djangoproject.com/en/1.11/topics/db/managers/), and simply hand back the relevant data to my views.py.

To achieve this, in my views.py, I create a dictionary with the full request object itself, I send this off for all validations/creations, and then check for errors upon the return, as a False is returned if any validation errors were flagged. Otherwise the success page will load with the new user.

views.py:

def register(request):
    if request.method == "POST":

        # Validate registration data submitted from registration form:
        validated = User.objects.register_validate(request)

        # If validation fails, load index page with request object 
        # (which `django messaging` has attached errors to):
        if validated == False:
                print "User could not be registered."
                # Send back index with updated request object:
                return render(request, "logreg/index.html")

        # If validation successful, create new user and send it along with success page:
        else:
            # Load success page with `validated` user (already returned as a `dict` obj.)
            return render(request, "logreg/success.html", validated)

models.py:

# Note: this function snippet is part of `class UserManager(models.Manager)`:
def register_validate(self, request):

    # Check if first_name or last_name is less than 2 characters:
    if len(request.POST["first_name"]) < 2 or len(request.POST["last_name"]) < 2:
        # Add error to Django's error messaging:
        messages.add_message(request, REG_ERR, 'First and last name are required must be at least 2 characters.', extra_tags="reg_errors")

    # ... more validations ...

    # Get current errors to check if any exist:
    errors = get_messages(request)

    # If no validation errors, hash password, create user and send new user back:
    if len(errors) == 0:
        # Hash Password:
        hashed_pwd = bcrypt.hashpw(request.POST["password"].encode(), bcrypt.gensalt(14))
        # Create new validated User:
        validated_user = {
            "logged_in_user": User(first_name=request.POST["first_name"], last_name=request.POST["last_name"], email=request.POST["email"], password=hashed_pwd)
        }
        # Save new User:
        validated_user["logged_in_user"].save()
        # Send newly created validated User back:
        return validated_user
    else:
       return False

Question:

Previously I had extracted all data from the request object via request.POST["my_data"] (did not pass the entire object but extracted what I needed into a custom dict), and was custom generating error messages. However, I wanted to practicing using django-messages, (of which requires the request object as a parameter, as this is what it attaches the errors to). Because I wanted all validations to occur in models.py, I sent my entire request object over (to then extract form data, but to also create new messages with django-messages).

Does passing the entire request object cause major drops in performance or is this bad practices? The fact that my learning lesson went so far out of the way to stress not passing the entire request object was a little confusing to me, especially considering to generate errors in my models.py via django-messages, I need access to the full object.

Any ideas?

Note: The other thought I had was to have my validation functions return a list of errors, to which I could iterate over and generate the django-messages errors (and using the request object in views.py), but this would place more logic/crunching on the controller, and was trying to keep everything nice and tight in the Manager (in models.py) for simplicity/organization.

Thanks in advance for reading, and let me know if I need to clarify any information here presented...was trying to provide a minimal chunk of my code to give context.

4

1 回答 1

0

附加整个request对象不一定会影响性能,但它确实会带来安全问题,就好像整个request对象都被发送到models.py,欺骗性请求可能会干扰预期的功能。

通过在 slack 频道中与其他开发人员交谈,听起来大多数人会在 中生成一个错误列表models.py,然后将其返回给views.py,他们在其中调用django-messages模块并创建他们的消息。主要论点是限制对request对象本身的访问,防止其models.py受到欺骗并降低来自欺骗请求的风险。

于 2017-05-19T02:51:02.313 回答