我扩展了用户模型并创建了从用户到客户模型的一对一关系。但是,每当我调用客户页面时,用户模型中的字段都不会在那里呈现。它只呈现一个字段,即字段名称中客户模型中的用户名,而不是将名字呈现为姓名、姓氏和电子邮件地址等。我怎样才能做到这一点?我需要使用用户注册中可用的信息填写客户表单。说得通?或者我试图做的实现是错误的。先感谢您。请参阅下面的models.py 和views.py 代码
models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.contrib.auth.models import Group
# Create your models here.
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True,on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
last_name = models.CharField(max_length=200, null=True, blank=True)
phone = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
city = models.CharField(max_length=200, null=True)
address_1 = models.CharField(max_length=200, null=True)
zip_code = models.CharField(max_length=5, null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return str(self.name)
#return self.name
# Using signals to post_save data
def customer_profile(sender, instance, created, **kwargs):
if created:
group = Group.objects.get(name='customer')
instance.groups.add(group)
Customer.objects.create(
user=instance,
name=instance.username,
)
print('Profile created!')
post_save.connect(customer_profile, sender=User)
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
#from django.urls import reverse_lazy
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import Group
from django.contrib import messages
from django.contrib.auth.decorators import login_required # in order to restrict views, login decorators
# Create your views here.
from .models import *
from .forms import CreateUserForm, EditProfileForm, CustomerForm
from .decorators import unauthenticated_user, allowed_users, admin_only
def home(request):
return render(request,'first_app/home.html')
def books(request):
return render(request,'first_app/books.html')
@unauthenticated_user
def registerPage(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm (request.POST)
if form.is_valid():
user = form.save()
username = form.cleaned_data.get('username')
#group = Group.objects.get(name ='customer') # replaced with signals on models.py
#user.groups.add(group)
#Customer.objects.create(
#user=user,
#name=user.username,
#)
messages.success(request,'Hello ' + username + ' Your account has been created')
return redirect('login')
context = {'form':form}
return render(request,'first_app/register.html', context)
@unauthenticated_user
def loginPage(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('profile')
else:
messages.info(request, 'Username or Password is Incorrect')
messages.info(request, 'Please Try Again')
context = {}
return render(request,'first_app/login.html', context)
def logoutUser(request):
logout(request)
return redirect('login')
@login_required(login_url='login') # in order to restrict views, login decorators
def profile(request):
#contex = {}
return render(request,'first_app/profile.html')
def base(request):
#contex = {}
return render(request,'first_app/base.html')
@login_required(login_url='login') # in order to restrict views, login decorators
def edit_profile(request):
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('profile')
else:
form = EditProfileForm(instance=request.user)
args = {'form': form}
return render(request, 'first_app/edit_profile.html', args)
def userPage(request):
context = {}
return render(request, 'first_app/user.html', context)
@login_required(login_url='login') # in order to restrict views, login decorators
def customer(request):
#customers = Customer.objects.all()
#context = {'customers':customers} # dictionary to passing the data below
customer = request.user.customer # using customer instance
form = CustomerForm(instance=customer) # using customer instance
#user = request.user
#form = CustomerForm(instance=user)
if request.method == 'POST':
form = CustomerForm(request.POST, instance=customer) # using customer instance
#form = CustomerForm(request.POST, instance=user)
if form.is_valid():
form.save()
context = {'form':form}
return render(request, 'first_app/customer.html', context)
forms.py
from django.forms import ModelForm
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
from django import forms
from .models import *
class CreateUserForm(UserCreationForm):
#fullname = forms.CharField(label="First name")
class Meta:
model = User
fields = ['first_name','last_name','username', 'email', 'password1', 'password2'] #Python list
class EditProfileForm(UserChangeForm):
#fullname = forms.CharField(label="First name")
class Meta:
model = User
fields = ['first_name','last_name','username', 'email'] #Python list
class CustomerForm(ModelForm):
class Meta:
model = Customer
fields = '__all__'
exclude = ['user']
答案 0 :(得分:2)
抱歉长篇幅..
我尝试从 django 中寻找内置解决方案,但找不到。
我能想到的最简单的事情就是表单本身只有两个模型。
这需要从用户模型中已经存在的 Customer
模型中删除一些字段。我也没有使用 customer_profile
post_save 信号。所以这些建议未经测试,除非它与可能发生的变化完全冗余。
在models.py
中修改
class Customer(models.Model):
user = models.OneToOneField(User, blank=True,on_delete=models.CASCADE)
phone = models.CharField(max_length=200, null=True)
city = models.CharField(max_length=200, null=True)
address_1 = models.CharField(max_length=200, null=True)
zip_code = models.CharField(max_length=5, null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return str(self.user.username)
当然还有运行迁移的提醒
python manage.py makemigrations first_app
python manage.py migrate
如果失败,请删除迁移文件夹和数据库文件并再次运行(假设数据库不包含任何值得保留的数据)。
添加到forms.py
class UserForm(ModelForm):
class Meta:
model = User
fields = [
'username',
'first_name',
'last_name',
'email'
]
widgets = {
'username': forms.TextInput(attrs={'readonly': True }),
'first_name': forms.TextInput(attrs={'readonly': True }),
'last_name': forms.TextInput(attrs={'readonly': True }),
'email': forms.TextInput(attrs={'readonly': True }),
}
help_texts = {
'username': ''
}
这些字段设置为只读且未禁用,否则它们将不会与表单一起提交。 username
字段也禁用了烦人的帮助文本。
那么您的 customer
视图可能如下所示
views.py
# add these imports
from django.contrib.auth.models import User
# add UserForm
from .forms import CreateUserForm, EditProfileForm, CustomerForm, UserForm
@login_required(login_url='login') # in order to restrict views, login decorators
def customer(request):
user = request.user
if request.method == 'POST':
# create customer
customer_form = CustomerForm(request.POST)
# check if customer already exists
# this allows customer details to be edited
# also stops unique key error if creating a customer for a user that already has a customer object
try:
customer = Customer.objects.get(user=user)
customer_form = CustomerForm(request.POST, instance=customer)
except Customer.DoesNotExist:
customer_form = CustomerForm(request.POST)
if customer_form.is_valid():
customer = customer_form.save(commit=False)
customer.user = user
customer.save()
# returning HttpResponse else you will reload the same page
return HttpResponse("Successfully saved Customer")
user_form = UserForm(instance=user)
customer_form = CustomerForm()
context = {
'user_form': user_form,
'customer_form': customer_form
}
return render(request, 'first_app/customer.html', context)
我不知道你的 customer.html
页面是什么样的,但下面的 html 会给出相应的输出。
customer.html
<h1>Customer Page</h1>
<form action="/customer" method="POST">
{% csrf_token %}
{{ user_form.as_p }}
{{ customer_form.as_p }}
<input type="submit" value="Create Customer"></input>
</form>
带有预先填充的相关字段的呈现表单。
数据库中的结果 Customer
对象
Customer
模型后执行以下操作。添加到forms.py
class UserForm(ModelForm):
class Meta:
model = User
fields = [
'username',
'first_name',
'last_name',
'email'
]
views.py
@login_required(login_url='login') # in order to restrict views, login decorators
def customer(request):
user = request.user
if request.method == 'POST':
# update user
user_form = UserForm(request.POST, instance=user)
if user_form.is_valid():
user_form.save()
# safety check if customer already exists
# this allows customer details to be edited
# also stops unique key error if creating a customer for a user that already has a customer object
try:
customer = Customer.objects.get(user=user)
customer_form = CustomerForm(request.POST, instance=customer)
except Customer.DoesNotExist:
customer_form = CustomerForm(request.POST)
# create customer
customer_form = CustomerForm(request.POST)
if customer_form.is_valid():
customer = customer_form.save(commit=False)
customer.user = user
customer.save()
# returning HttpResponse else you will reload the same page
return HttpResponse("Successfully saved Customer")
user_form = UserForm(instance=user)
customer_form = CustomerForm()
context = {
'user_form': user_form,
'customer_form': customer_form
}
return render(request, 'first_app/customer.html', context)
customer.html(与上一个示例相同)
<h1>Customer Page</h1>
<form action="/customer" method="POST">
{% csrf_token %}
{{ user_form.as_p }}
{{ customer_form.as_p }}
<input type="submit" value="Create Customer"></input>
</form>
表单中用户详细信息的示例更新
答案 1 :(得分:0)
这样想。
Django 默认 User
模型具有:
['first_name','last_name','username', 'email', 'password1', 'password2']
您不必再次将它们存储在 Customer
模型中,而是可以更新它们。
在 Customer
模型中删除以下字段:
['name','last_name', 'email']
因此您的 Customer
模型将如下所示:
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True,on_delete=models.CASCADE)
phone = models.CharField(max_length=200, null=True)
city = models.CharField(max_length=200, null=True)
address_1 = models.CharField(max_length=200, null=True)
zip_code = models.CharField(max_length=5, null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return str(self.user.username)
那么您的 customer_profile
信号将类似于:
def customer_profile(sender, instance, created, **kwargs):
if created:
group = Group.objects.get(name='customer')
instance.groups.add(group)
Customer.objects.create(
user=instance,
)
print('Profile created!')
post_save.connect(customer_profile, sender=User)
现在你有两页。
一个是用于更新值的 edit profile
页面:
['first_name','last_name','username', 'email']
Other 用于填充 Customer
模型字段:
['phone','city','address_1', 'zip_code']