Django:在模型表单中使用 ImageField

Django: Use ImageField in Modelforms

所以我有这个模型形式:

User = get_user_model()
class UserRegisterForm(forms.ModelForm):
    username = forms.CharField(label='', widget=forms.TextInput(attrs={'placeholder': 'Username'}))
    email = forms.EmailField(label='', widget=forms.TextInput(attrs={'placeholder': 'Email Address'}))
    email2 = forms.EmailField(label='', widget=forms.TextInput(attrs={'placeholder': 'Confirm Email'}))
    password = forms.CharField(label='', widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
    avatar = forms.ImageField(upload_to='profile_images')

class Meta:
    model = User 
    fields = [
        'username',
        'email',
        'email2',
        'password'
    ]

但是这个出现

TypeError: __init__() got an unexpected keyword argument 'upload_to'

问题是,如果我将 ImageField 对象添加到模型中,我认为它会起作用,但我没有模型,如您所见,我正在使用 get_user_model(),是否有在模型表单中使用 upload_to 的方法,或者我如何添加到默认的 'get_user_model' ImageField 对象?

你应该制作一个额外的模型来存储头像,或者你可以制作一个custom user model

如果你制作一个额外的模型,例如Profile,你可以将其定义为:

# app/models.py

from django.conf import settings
from django.db import models

class Profile(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        editable=False
    )
    avatar = models.ImageField(upload_to='profile_images/')

然后你可以做两个ModelForm例如。事实上,对于 User,您最好使用 UserCreationForm [Django-doc],因为它已经实现了验证密码是否匹配的逻辑,并且它还会透明地散列密码。

因此,您可以为 Profile 定义一个 ModelForm,并使用:

# app/forms.py

from django import forms
from app.models import Profile

class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['avatar']

在视图中,您可以使用两种形式:

# app/views.py

from app.forms import ProfileForm
from django.contrib.auth.forms import UserCreationForm

def some_view(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST, request.FILES)
        form2 = ProfileForm(request.POST, request.FILES)
        if form.is_valid() and form2.is_valid():
            user = form.save()
            form2<b>.instance.user = user</b>
            form2.save()
            return redirect(<i>'name-of-some-other-view'</i>)
    else:
        form = UserCreationForm()
        form2 = ProfileForm()
    return render(request, <i>'name-of-some-template.html'</i>, {'form': form, 'form2': form2})

因此您在同一个 <form> 标签中呈现两种形式:

<form action="{% url 'some_view' %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ <b>form</b> }}
    {{ <b>form2</b> }}
</form>