Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - alter post data in CreateView

I am trying to change a value in a post request but am getting the following error:

IntegrityError: null value in column "owner" violates not-null constraint
DETAIL:  Failing row contains (30, 123, G, null) <--> (index, number, type, owner)

The form itself:

<form method="post">
    {% csrf_token %}
    {{form.number}}
    {{form.type}}
    <input type="hidden" value="{{variable}}" name="owner">
    <button type="submit">Save</button>
</form>

The request.POST data:

<QueryDict: {'csrfmiddlewaretoken': ['TN3yNiGcvAso6V1UYZDHpyIQ1sNTMqDICPSqX2sftVpZfX6drambOkzoGBECLKcN'], 'number': ['123'], 'type': ['G'], 'owner': ['']}>

To modify the data:

class NodeCreateView(CreateView):

model = Node
form_class = NodeCreateForm
...

def post(self, request, **kwargs):
    request.POST = request.POST.copy()
    request.POST['owner'] = 2
    return super(NodeCreateView, self).post(request, **kwargs)

The updated POST data:

<QueryDict: {'csrfmiddlewaretoken': ['TN3yNiGcvAso6V1UYZDHpyIQ1sNTMqDICPSqX2sftVpZfX6drambOkzoGBECLKcN'], 'number': ['123'], 'type': ['G'], 'owner': [2]}>

Where am I going wrong?

like image 614
William Avatar asked Jul 28 '26 12:07

William


2 Answers

You don't have to include the owner as a hidden input, or modify the post data like this.

First, exclude the owner from your form:

class NodeCreateForm(forms.ModelForm):
    class Meta:
        model = Node
        exclude = ['owner']

Then in your view, override the form_valid method, and set the owner_id on the instance:

class NodeCreateView(CreateView):
    model = Node
    form_class = NodeCreateForm

    def form_valid(self, form):
        form.instance.owner_id = 2
        return super(NodeCreateView, self).form_valid(form)

I'm assuming owner is a foreign key, otherwise set form.instance.owner = 2.

like image 154
Alasdair Avatar answered Jul 31 '26 00:07

Alasdair


You're correctly mutating request.POST by using copy(), but passing the modified request object into super().post() is misleading. If you follow the call chain back to where the view is actually accessing the request object, it's not using your modified request, it's using the un-modified request as self.request. See here.

There is probably a better way to accomplish whatever it is you're doing, but if it's nothing permanent, you can just override get_form_kwargs() in your NodeCreateView.

like image 43
mindcruzer Avatar answered Jul 31 '26 00:07

mindcruzer