【问题标题】:Django Model Form, One-to-OneField with another model, update fields in both modelsDjango 模型表单,与另一个模型的一对一字段,更新两个模型中的字段
【发布时间】:2016-02-12 07:30:34
【问题描述】:

我正在使用django.contrib.auth.models User model。我还有另一个名为 UserProfile 的类,它本质上是 django 用户模型的扩展。

class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='userprofile', primary_key=True)
    age = models.CharField(max_length=3, blank=True)
    shortbio = models.CharField(max_length=400, blank=True)

所以我想有一个基于UserProfile 模型的表单,而且还整合了User 类中的名字和姓氏等现有字段。并允许我以一种形式更新UserProfileUser 的两个字段。我该如何处理?

【问题讨论】:

标签: python django django-models django-forms modelform


【解决方案1】:

有 3 个步骤可以实现这一目标。我昨天碰巧做了一件非常相似的事情。首先是模型,然后是视图,然后是模板。

型号:

此代码可确保在用户注册时也会创建新的个人资料。在 UserProfile 下添加此代码,不带标签。

# This will ensure the profile is made when a user is created
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

观看次数:

我会假设这个表格是用于注册的,就像我的一样。这(对我而言)需要大量代码,因为您需要做一些事情。 (1) 保存新用户。 (2) 设置新的用户配置文件 (3) 保存用户配置文件

# This method will allow a user to register for an account
def register_user(request):
    form1 = UserForm(prefix="user")
    form2 = ProfileForm(prefix="profile")

    if request.method == "POST":
        form1 = UserForm(request.POST, prefix="user")
        form2 = ProfileForm(request.POST, prefix="profile")

        if form1.is_valid() and form2.is_valid():
            # Save form1 with no commit
            user = form1.save(commit=False) 
            # Code you may add for your website registration, example
            # user.email = form1.cleaned_data['email'] 
            user.save()
            user.userprofile.user = user
            user.userprofile.age = form2.cleaned_data['age']
            user.userprofile.bio = form2.cleaned_data['bio']
            user.userprofile.save()
            # Some return statement you choose
            return redirect('app_name:index')
    # ***
    return render(request, 'accounts/register.html', {"form1": form1, "form2": form2}) 

注意:即使不是用于寄存器,此代码也应该相似。无论如何,您基本上都需要重置所有内容。

模板:

这很简单。在 forms.py 中制作您自己的用户表单和个人资料表单,然后将它们返回到您的视图函数。注意最后一行的 ***。然后在您的模板中添加:

<h4>Register for an Account</h4>
{% if error_message %}
     <p><strong>{{ error_message }}</strong></p>
{% endif %}

<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
   {% csrf_token %}
   {{form1}}
   {{form2}}
   <br>
   <div class="form-group">
       <div class="col-sm-offset-2 col-sm-10">
             <button type="submit" class="btn btn-success">Submit</button>
       </div>
   </div>
</form>

【讨论】:

    【解决方案2】:

    有一些方法可以做到,这里有一个:

    网址:

    from app import views
    from app import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^complementary/', views.complementary)
    ]
    

    型号:

    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
    
    from django.contrib.auth.models import User
    from django.db import models
    
    
    # Create your models here.
    class UserProfile(models.Model):
        user_p = models.OneToOneField(User, related_name='userprofile',
                                    primary_key=True)
        age = models.CharField(max_length=3, blank=True)
        shortbio = models.CharField(max_length=400, blank=True)
    

    观看次数:

    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
    
    from django.shortcuts import redirect
    from django.shortcuts import render
    
    from app.forms import UserEditForm, ProfileEditForm
    from app.models import UserProfile
    
    
    # Create your views here.
    def complementary(request):
        profile = UserProfile.objects.get(user_p=1)
        user_form = UserEditForm(instance=request.user)
        profile_form = ProfileEditForm(instance=request.user)
    
        if request.method == 'POST':
            user_form = UserEditForm(instance=request.user,
                                     data=request.POST)
            profile_form = ProfileEditForm(instance=request.user.usuario,
                                           data=request.POST,
                                           files=request.FILES)
    
            if user_form.is_valid() and profile_form.is_valid():
                user_form.save()
                profile_form.save()
                return redirect('redirect_url')
    
        dic = {'profile': profile,
               'user_form': user_form,
               'profile_form': profile_form}
    
        return render(request, 'template.html', dic)
    

    表格:

    # -*- coding: utf-8 -*-
    from django import forms
    from django.contrib.auth.models import User
    from django.core.validators import RegexValidator
    from app.models import UserProfile
    
    
    class UserEditForm(forms.ModelForm):
        # Regex for non-digits
        name_val = [RegexValidator(r'^[a-zA-ZÀ-Ÿ_]+( [a-zA-ZÀ-Ÿ_]+)*$',
                                   message='Non-digits',
                                   code='invalid_name')]
    
        first_name = forms.CharField(
            label='Name *',
            validators=name_val,
            widget=forms.TextInput(attrs={'placeholder': 'Name: '})
        )
        last_name = forms.CharField(
            label='Last Name *',
            validators=name_val,
            widget=forms.TextInput(attrs={'placeholder': 'Last Name: '})
        )
    
        class Meta:
            model = User
            fields = ('first_name', 'last_name', 'email')
    
    
    class ProfileEditForm(forms.ModelForm):
        class Meta:
            model = UserProfile
            exclude = 'id',
    

    模板.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        {{ profile.shortbio }}
        <form role="form" method="post" id="custom-form">
            {% csrf_token %}
            {{ user_form.as_p }}
            {{ profile_form.as_p }}
            <button type="submit"></button>
        </form>
    </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-25
      • 2017-01-31
      • 2019-03-11
      • 2011-05-21
      • 2015-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多