You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自动设置表单提交用户为模型外键字段的报错与实现需求

Hey there! Let's fix that save() missing required positional argument 'self' error while automatically assigning the current user to your model's foreign key field. I'll walk you through a solid, working example step by step—no fancy tricks, just straightforward Django practices.

1. Define Your Model First

Let's start with a simple model that has a user foreign key (linked to Django's built-in User model) and some other fields. This is our base:

# models.py
from django.db import models
from django.contrib.auth.models import User

class Post(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    content = models.TextField()

    def __str__(self):
        return self.title
2. Build the Form (Exclude the User Field)

We don't want the user to manually select their own account, so we'll exclude the user field from our form. Django will handle setting it automatically:

# forms.py
from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content']  # Only include fields users need to fill out
3. Handle the Form in Views (Two Reliable Approaches)

I'll show you two common, error-free ways to assign the user. Pick whichever fits your workflow better.

Approach 1: Set the User Directly in the View (Most Straightforward)

This method uses commit=False to create a model instance without saving it to the database first. We can then add the user before saving:

# views.py
from django.shortcuts import render, redirect
from .forms import PostForm
from django.contrib.auth.decorators import login_required

@login_required  # Make sure only logged-in users can submit the form
def create_post(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            # Create the Post instance but don't save to DB yet
            post = form.save(commit=False)
            # Assign the current logged-in user
            post.user = request.user
            # Now save the complete instance to the database
            post.save()
            return redirect('post_list')  # Replace with your desired redirect URL
    else:
        form = PostForm()
    return render(request, 'create_post.html', {'form': form})

Approach 2: Override the Form's Save Method

If you prefer to keep view logic clean, you can move the user assignment into the form itself by overriding the save() method:

First, update your form:

# forms.py (updated)
from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content']

    # Override save to accept a user parameter
    def save(self, user, commit=True):
        # Get the unsaved instance from the parent save method
        instance = super().save(commit=False)
        # Assign the user
        instance.user = user
        # Save to DB if commit is True
        if commit:
            instance.save()
        return instance

Then update your view to pass the user to the form's save method:

# views.py (updated for Approach 2)
from django.shortcuts import render, redirect
from .forms import PostForm
from django.contrib.auth.decorators import login_required

@login_required
def create_post(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            # Pass the current user to our custom save method
            form.save(user=request.user)
            return redirect('post_list')
    else:
        form = PostForm()
    return render(request, 'create_post.html', {'form': form})
Why You Got the "save() missing 'self'" Error?

Chances are you tried calling the save method directly on the model class instead of an instance. For example:

# ❌ Wrong! This will throw the error because save() is an instance method
if form.is_valid():
    Post.save(user=request.user)

You need to create an instance first (like we did with form.save(commit=False)) before calling save().

Bonus: Simple Template Example

Here's a quick template to render the form (save this as create_post.html):

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Submit Post</button>
</form>

内容的提问来源于stack exchange,提问作者Derrick Sherrill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:54:22