Opened 19 years ago

Closed 19 years ago

Last modified 18 years ago

#298 closed enhancement (wontfix)

Need impovement to POST.copy()

Reported by: mr_little Owned by: Adrian Holovaty
Component: Core (Other) Version:
Severity: normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When i need to change only few fields of model, for example only date_start field of Project, i need to pass a values of other fields like new_data variable into manipulator.* methods ('coz they are not present in POST)

The only place of values of other fields is Project.dict

But manipulator.* methods expects new_data.values() like strings. And Project.dict contains .values() like python-values.

Also, new_data must be MultiValueDict

So, i need to make new_data like this (it's a simple shortened example without checks):

def start(req, p_id):
    """
    Updates "start" information about project
    Such as start_date, start_people e.t.c.
    """
    try:
        prj = projects.get_object(pk=rp_id)
    except projects.ProjectDoesNotExist:
        raise Http404

    manipulator = projects.ChangeManipulator(prj.id)
    new_data = prj.__dict__ # all fields of Project
            
    errors = dict()
            
    if req.POST:
        #only tree fields changed, and values of them are in req.POST
        new_data = update_post(req.POST.copy(), new_data)
        errors = manipulator.get_validation_errors(new_data)
        
        mnp.do_html2python(new_data)
        mnp.save(new_data)

Where the update_post() is like this:

def update_post(post, data):
    for key in data:
        if not key in post.keys():
            if data[key]:
                post[key]=str(data[key])
            else:
                post[key]=''
    return post

But it's easy to say:

    new_data = req.POST.copy(new_data) # default values like param
#or
    new_data.update(req.POST)

or something like this...

Change History (6)

comment:1 by Adrian Holovaty, 19 years ago

Resolution: invalid
Status: newclosed

Please explain this better. I don't really understand what you're trying to do.

comment:2 by mr_little, 19 years ago

Resolution: invalid
Status: closedreopened

Look at example:

Model Project, has

project_name
date_start
date_end

The view StartProject has only one form-field and submit button

[date_start] [OK]

when we starting project - it's no need to change it's name or date_end

I want to use manipulator's form fields to draw, and to validate that 'start_date'
So, when i press [OK], request.POST in code contains only that field {'start_date':date}
but it doesn't contains 'project_name' and 'date_end' fields which are required for manipulator.save() method

So i need to emulate:

  1. get that fields from Project.dict
  2. transform it to strings (becoz manipulator's validators expects strings, not python values)
  3. add that fields to new_data dict

There are would be clear if step 1 - 3 will be a "feature" of POST.copy() method

Simply - when i pass Project.dict to the POST.copy() method it get's values from that dict, and adds that values to the result, like strings.

So, manipulator thoughs that fields a passed from the POST request :)

comment:3 by Jacob, 19 years ago

Resolution: wontfix
Status: reopenedclosed

The thing is, request.POST emulates a dictionary, and in Python dict.copy() doesn't take an argument. It seems stupid to have a dict-like object that deviates from the object it's emulating.

Besides, this is extremely easy to do:

new_data = project.__dict__
new_data = new_data.update(request.POST.copy())

That's clear, concise, and immediately obvious, whereas:

new_data = request.POST.copy(Project.__dict__)

Might be shorter, but is unclear -- is Project.__dict__ overriding values in request.POST, or is it the other way around? For that matter, what's getting copied?

comment:4 by mr_little, 19 years ago

Resolution: wontfix
Status: closedreopened

two mistakes in your example:

1.

  new_data = project.__dict__ # new data type is dict
  new_data = new_data.update(request.POST.copy()) # new data type is dict but must be MultiValueDict like request.POST
  1. values in new_data are python values from project.__dict__ but must be strings (for validators)

The second condition is worst :(

comment:5 by hugo <gb@…>, 19 years ago

from utils.datastructures import MultiValueDict

new_data = MultiValueDict(dict([(k, [str(v)]) for (k, v) in project.__dict__.items()]))
new_data = new_data.update(request.POST.copy())

that should do the trick and convert all values to strings.

comment:6 by Adrian Holovaty, 19 years ago

Resolution: wontfix
Status: reopenedclosed
Note: See TracTickets for help on using tickets.
Back to Top