django 扩展页面不从注册页面呈现值(用户 django 模型)

时间:2021-01-31 16:37:46

标签: django

我扩展了用户模型并创建了从用户到客户模型的一对一关系。但是,每当我调用客户页面时,用户模型中的字段都不会在那里呈现。它只呈现一个字段,即字段名称中客户模型中的用户名,而不是将名字呈现为姓名、姓氏和电子邮件地址等。我怎样才能做到这一点?我需要使用用户注册中可用的信息填写客户表单。说得通?或者我试图做的实现是错误的。先感谢您。请参阅下面的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']

2 个答案:

答案 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>

在用户表中测试用户 test user in db

带有预先填充的相关字段的呈现表单。

rendered form with all fields

数据库中的结果 Customer 对象

Customer object in db

如果您希望客户能够编辑他们的用户数据,请在更改 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>

表单中用户详细信息的示例更新

rendered form with edited user details

数据库中更新的用户 updated user

答案 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']