我有一个自定义User
模型来管理一些个人资料用户:is_student
,is_professor
和is_executive
在此模型中,我还使用get_student_profile()
,get_professor_profile()
和get_executive_profile()
方法从我的不同视图中获取每个用户的用户个人资料数据。
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
slug = models.SlugField(max_length=100, blank=True)
is_student = models.BooleanField(default=False)
is_professor = models.BooleanField(default=False)
is_executive = models.BooleanField(default=False)
def get_student_profile(self):
student_profile = None
if hasattr(self, 'studentprofile'):
student_profile = self.studentprofile
return student_profile
def get_professor_profile(self):
professor_profile = None
if hasattr(self, 'professorprofile'):
professor_profile = self.professorprofile
return professor_profile
def get_executive_profile(self):
executive_profile = None
if hasattr(self, 'executiveprofile'):
executive_profile = self.executiveprofile
return executive_profile
此外,每个个人资料用户is_student
,is_professor
和is_executive
都有自己的模型,我可以在其中管理自己的数据:
class StudentProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(max_length=100,blank=True)
origin_education_school = models.CharField(max_length=128)
current_education_school = models.CharField(max_length=128)
extra_occupation = models.CharField(max_length=128)
class ProfessorProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(max_length=100,blank=True)
class ExecutiveProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(max_length=100,blank=True)
就是这样,在我的User
模型中,我覆盖了save()
方法,以表示创建的用户的username
字段,其值与属于个人资料用户的slug
将吸引该用户(StudentProfile
,ProfessorProfile
,ExecutiveProfile
):
def save(self, *args, **kwargs):
user = super(User,self).save(*args,**kwargs)
# Creating an user with student, professor and executive profiles
if self.is_student and not StudentProfile.objects.filter(user=self).exists() \
and self.is_professor and not ProfessorProfile.objects.filter(user=self).exists() \
and self.is_executive and not ExecutiveProfile.objects.filter(user=self).exists():
student_profile = StudentProfile(user=self)
student_slug = self.username
student_profile.slug = student_slug
professor_profile = ProfessorProfile(user=self)
professor_slug = self.username
professor_profile.slug = professor_slug
executive_profile = ExecutiveProfile(user=self)
executive_slug = self.username
executive_profile.slug = executive_slug
student_profile.save()
professor_profile.save()
executive_profile.save()
# And so for all possibles profile combinations
对于这三个配置文件,我在其中生成了自己的字段的三种形式
class StudentProfileForm(forms.ModelForm):
class Meta:
model = StudentProfile
fields = ('origin_education_school', 'current_education_school',
'extra_occupation')
class ProfessorProfileForm(forms.ModelForm):
class Meta:
model = ProfessorProfile
fields = ('occupation',)
class ExecutiveProfileForm(forms.ModelForm):
class Meta:
model = ExecutiveProfile
fields = ('occupation', 'enterprise_name', 'culturals_arthistic','ecological')
我通过以下网址访问用户查看个人资料:
url(r"^profile/(?P<slug>[\w\-]+)/$",
views.account_profiles__update_view,
name='profile'
),
在我的基于功能的视图account_profiles__update_view()
中,我正在管理用户的请求,并根据个人资料创建表单实例(StudentProfileForm
,ProfessorProfileForm
,ExecutiveProfileForm
)用户(is_student
,is_professor
和is_executive
)
@login_required
def account_profiles__update_view(request, slug):
user = request.user
# user = get_object_or_404(User, username = slug)
# empty list
_forms = []
if user.is_student:
profile = user.get_student_profile()
_forms.append(forms.StudentProfileForm)
if user.is_professor:
profile = user.get_professor_profile()
_forms.append(forms.ProfessorProfileForm)
if user.is_executive:
profile = user.get_executive_profile()
_forms.append(forms.ExecutiveProfileForm)
# user = get_object_or_404(settings.AUTH_USER_MODEL, username = slug)
if request.method == 'POST':
# Create a list with all formularies in which there is some POST
# operation. This mean if there is one, two or three profiles together
# or individual
formularios =[Form(data = request.POST,instance=profile) for Form in _forms]
if all([form.is_valid() for form in formularios]):
# Only save dato to database if all formularies that send
# the user in their request are correct or well formed in their
# data. Check that all formularies has been filled
for form in formularios:
profile = form.save(commit=False)
profile.user = user
profile.save()
return redirect('dashboard')
else:
formularios = [Form() for Form in _forms]
# Access to class Forms instanced (StudentProfileForm,
# ProfessorProfileForm, ExecutiveProfileForm), through the __class__
# pŕoperty which return the class onlying. An this class have another
# property named __name__ which return the name of string of a class,
# which is the same name with I did name the form classes
# (StudentProfileForm, ProfessorProfileForm, ExecutiveProfileForm)
# Next I call to their string method to grant that I always will return
# a string and I call to lower.
# The idea with this is place data into a python dictionarie and access
# to it
data = {form.__class__.__name__.__str__().lower(): form for form in formularios}
data['userprofile'] = profile
return render(request, 'accounts/profile_form.html', data,)
我的profile_form.html
模板我有以下小逻辑:
<form method="POST">
{% csrf_token %}
{% if userprofile.user.is_student %}
<div align="center"><i>My Student Profile data</i></div>
{% bootstrap_form studentprofileform %}
{{ studentprofileform.non_field_errors }}
{% endif %}
{% if userprofile.user.is_professor %}
<div align="center"><i>My Professor Profile data</i></div>
{% bootstrap_form professorprofileform %}
{{ professorprofileform.non_field_errors }}
{% endif %}
{% if userprofile.user.is_executive %}
<div align="center"><i>My Executive Profile data</i></div>
{% bootstrap_form executiveprofileform %}
{{ executiveprofileform.non_field_errors }}
{% endif %}
<input type="submit" value="Save Changes" class="btn btn-default">
</form>
我想写下所有这些细节来评论发生在我身上的以下情况:
我在模板中渲染了三个表单
仅存储与所选最新用户个人资料相关的数据,这意味着:
个人资料:is_student
,is_professor
和is_executive
is_student
个人资料的用户...保存数据is_professor
个人资料的用户...保存数据拥有is_executive
个人资料的用户...保存数据
拥有is_student
和is_professor
个人资料的用户:仅将数据保存到is_professor
个人资料。不在is_student
个人资料表单字段
拥有is_student
和is_executive
个人资料的用户:仅将数据保存到is_executive
个人资料。不在is_student
个人资料表单字段
拥有is_professor
和is_executive
个人资料的用户:仅将数据保存到is_executive
个人资料。不在is_professor
个人资料表单字段
拥有is_student
,is_professor
和is_executive
个人资料的用户:仅将数据保存到is_executive
个人资料。不保存is_professor
和is_student
个人资料表单字段
此时,只会考虑最新选择的个人资料用户,并根据它保存他们的相关数据,而不是其他。
这是因为在account_profiles__update_view()
基于函数的视图中我有if
句子逻辑:
if user.is_student:
profile = user.get_student_profile()
_forms.append(forms.StudentProfileForm)
if user.is_professor:
profile = user.get_professor_profile()
_forms.append(forms.ProfessorProfileForm)
if user.is_executive:
profile = user.get_executive_profile()
_forms.append(forms.ExecutiveProfileForm)
但是,我不知道我是否应该考虑在这里执行所有配置文件用户组合的可能性,并创建相同的表单实例组合。这可以表现吗?
我尝试使用perfom account_profiles__update_view()
作为基于类的视图here some code about it,但是配置文件和实例表单的特征发送到模板,让我选择基于函数的视图选项。
¿什么是最好的选择?
对于长期问题我道歉,我确实希望提供所有细节,以便更好地理解我想要完成的代码和方法。 我非常感谢一些支持和指导。
答案 0 :(得分:1)
我冒昧地为你清理一些东西。让我们回顾一下每件作品。
<小时/>
无需使用hasattr()
探测模型。我们可以使用这样一个事实:用户和个人资料之间的OneToOneField
将在关系的两边放置一个引用。这意味着您可以简单地覆盖save()
方法,如下所示:
注意:您可能更愿意使用Signals创建个人资料。
from django.conf import settings
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.db import models
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
slug = models.SlugField(max_length=100, blank=True)
is_student = models.BooleanField(default=False, help_text="User is student")
is_professor = models.BooleanField(default=False, help_text="User is professor")
is_executive = models.BooleanField(default=False, help_text="User is executive")
USERNAME_FIELD = 'email'
def save(self, *args, **kwargs):
super(User, self).save(*args, **kwargs)
if self.is_student and getattr(self, 'studentprofile', None) is None:
StudentProfile.objects.create(
user=self,
slug=self.username
)
if self.is_professor and getattr(self, 'professorprofile', None) is None:
ProfessorProfile.objects.create(
user=self,
slug=self.username
)
if self.is_executive and getattr(self, 'executiveprofile', None) is None:
ExecutiveProfile.objects.create(
user=self,
slug=self.username
)
再次,让我们只使用用户OneToOneField
将包含对个人资料的引用这一事实:
@login_required
def update_view(request):
user = request.user
# Populate Forms and Instances (if applicable)
form_profiles = []
if user.is_student:
form_profiles.append({'form': StudentProfileForm, 'instance': user.studentprofile})
if user.is_professor:
form_profiles.append({'form': ProfessorProfileForm, 'instance': user.professorprofile})
if user.is_executive:
form_profiles.append({'form': ExecutiveProfileForm, 'instance': user.executiveprofile})
if request.method == 'POST':
forms = [x['form'](data=request.POST, instance=x['instance']) for x in form_profiles]
if all([form.is_valid() for form in forms]):
for form in forms:
form.save()
return redirect('dashboard')
else:
forms = [x['form'](instance=x['instance']) for x in form_profiles]
return render(request, 'accounts/profile_form.html', {'forms': forms})
您的表单可能如下所示:
class StudentProfileForm(forms.ModelForm):
title = "Student Form"
class Meta:
model = StudentProfile
fields = (
'origin_education_school',
'current_education_school',
'extra_occupation',
)
<form method="post">
{% csrf_token %}
{% for form in forms %}
<h1>{{ form.title }}</h1>
{{ form }}
{% endfor %}
<button type="submit">Submit</button>
</form>
我仔细检查,表格保存正确。
P.S。如果您想使用基于类的视图,可以按照本要点定义的类进行操作:https://gist.github.com/michelts/1029336