我有一个自定义Django用户架构来管理角色或用户类型:
由于我的AbstractBaseUser模型的一部分保持如此:
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)
other fields ...
我有get_student_profile()
,get_professor_profile()
和get_executive_profile()
方法来获取配置文件用户数据。
我在我的自定义模型save()
中覆盖User
方法,以便在创建用户时检查is_student或is_professor或is_executive时保存配置文件数据,他们的数据将保存在各自的型号:
class StudentProfile(models.Model):
user = models.OneToOneField(User,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):
CATHEDRAL_PROFESSOR = 'CATHEDRAL'
RESEARCH_PROFESSOR = 'RESEARCH'
INSTITUTIONAL_DIRECTIVE = 'DIRECTIVE'
OCCUPATION_CHOICES = (
(CATHEDRAL_PROFESSOR, 'Cathedral Professor'),
(RESEARCH_PROFESSOR, 'Research Professor'),
(INSTITUTIONAL_DIRECTIVE, 'Institutional Directive'),
)
user = models.OneToOneField(User,on_delete=models.CASCADE)
slug = models.SlugField(max_length=100,blank=True)
occupation = models.CharField(max_length=255,blank = False)
class ExecutiveProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
slug = models.SlugField(max_length=100, blank=True)
occupation = models.CharField(max_length=255,blank = False)
enterprise_name = models.CharField(max_length=255,blank = False)
我有每个配置文件用户的表单
class UserUpdateForm(forms.ModelForm):
class Meta:
widgets = {'gender':forms.RadioSelect,}
fields = ("username", "email", "is_student", "is_professor", "is_executive",)
model = get_user_model() #My model User
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.AccountProfilesView.as_view(
model=ProfessorProfile),
name='profile'
),
在我的AccountProfilesView
我管理个人资料表单并将其发送到模板
class AccountProfilesView(LoginRequiredMixin, UpdateView):
# All users can access this view
model = get_user_model()
success_url = reverse_lazy('dashboard')
template_name = 'accounts/profile_form.html'
fields = '__all__'
def get_context_data(self, **kwargs):
context = super(AccountProfilesView, self).get_context_data(**kwargs)
user = self.request.user
if not self.request.POST:
if user.is_student:
profile = user.get_student_profile()
context['userprofile'] = profile
context['form_student'] = forms.StudentProfileForm()
elif user.is_professor:
profile = user.get_professor_profile()
context['userprofile'] = profile
context['form_professor'] = forms.ProfessorProfileForm()
print ("profesor form is", context['form_professor'])
elif user.is_executive:
profile = user.get_executive_profile()
context['userprofile'] = profile
context['form_executive'] = forms.ExecutiveProfileForm()
elif user.is_student and user.is_professor and user.is_executive:
student_profile = user.get_student_profile()
professor_profile = user.get_professor_profile()
executive_profile = user.get_executive_profile()
context['student_profile'] = student_profile
context['professor_profile'] = professor_profile
context['executive_form'] = executive_profile
student_form = forms.StudentProfileForm()
professor_form = forms.ProfessorProfileForm()
executive_form = forms.ExecutiveProfileForm()
context['form_student'] = student_form
context['form_professor'] = professor_form
context['form_executive'] = executive_form
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
context = super(AccountProfilesView, self).post(request, *args, **kwargs)
user = self.request.user
if user.is_student:
context['form_student'] = forms.StudentProfileForm(self.request.POST)
elif user.is_professor:
context['form_professor'] = forms.ProfessorProfileForm(self.request.POST)
elif user.is_executive:
context['form_executive'] = forms.ExecutiveProfileForm(self.request.POST)
elif user.is_student and user.is_professor and user.is_executive:
context['form_student'] = forms.StudentProfileForm(self.request.POST)
context['form_professor'] = forms.ProfessorProfileForm(self.request.POST)
context['form_executive'] = forms.ExecutiveProfileForm(self.request.POST)
return context
def form_valid(self, form):
context = self.get_context_data(form=form)
user = self.request.user
user = form.save()
if user.is_student:
student = context['form_student'].save(commit=False)
student.user = user
student.save()
elif user.is_professor:
professor = context['form_professor'].save(commit=False)
professor.user = user
professor.save()
elif user.is_executive:
executive = context['form_executive'].save(commit=False)
executive.user = user
executive.save()
elif user.is_student and user.is_professor and user.is_executive:
student = context['form_student'].save(commit=False)
student.user = user
student.save()
professor = context['form_professor'].save(commit=False)
professor.user = user
professor.save()
executive = context['form_executive'].save(commit=False)
executive.user = user
executive.save()
return super(AccountProfilesView, self).form_valid(form)
get_context_data()
方法中context['form_professor'] = forms.ProfessorProfileForm()
和context['form_executive'] = forms.ExecutiveProfileForm()
未传递给模板的情况发生了什么
当我创建具有学生资料(is_student
)或教授资料(is_professor
)或执行资料(is_executive
)的用户时,一切正常,这对用户来说是正常的通过分隔的配置文件(仅具有一个配置文件的用户),呈现形式配置文件根据要分配的字段显示表单。
从这个意义上讲,在get_context_data()
部分中,以下代码可以正常工作并传递表单:
if user.is_student:
profile = user.get_student_profile()
context['userprofile'] = profile
context['form_student'] = forms.StudentProfileForm()
elif user.is_professor:
profile = user.get_professor_profile()
context['userprofile'] = profile
context['form_professor'] = forms.ProfessorProfileForm()
print ("profesor form is", context['form_professor'])
elif user.is_executive:
profile = user.get_executive_profile()
context['userprofile'] = profile
context['form_executive'] = forms.ExecutiveProfileForm()
但是当我创建一个已选中三个配置文件的用户(is_student
,is_professor
,is_executive
)时,只需传递context['form_student'] = forms.StudentProfileForm()
我显示数据的模板是:
{% extends 'layout.html' %}
{% load bootstrap3 %}
{% block title_tag %}Accounts | Profile | iHost {{ block.super }}{% endblock %}
{% block body_content %}
<div class="container">
<h1>My Profile</h1>
<form method="POST">
{% csrf_token %}
# I ask for user profile of a separate way
# Student Profile User
{% if userprofile.user.is_student %}
<br/><hr>
Student form
{% bootstrap_form form_student %}
{% endif %}
# Professor Profile User
{% if userprofile.user.is_professor %}
{{ form_professor.as_p }}
{% endif %}
# Executive Profile User
{% if userprofile.user.is_executive %}
{{ form_executive.as_p }}
{% comment %} {% bootstrap_form form_executive %}{% endcomment %}
{% endif %}
# I ask for an user with three profiles
{% if userprofile.user.is_student %}
<br/><hr>
Student form
{% if userprofile.user.is_professor %}
{% if userprofile.user.is_executive %}
{% bootstrap_form form_student %}
<br/><hr>
Professor form does not arrive
{{ form_professor.as_p }}
{% comment %} {% bootstrap_form form_professor %}{% endcomment %}
<br/><hr>
Executive form does not arrive
{{ form_executive.as_p }}
{% comment %}
{% bootstrap_form form_student %}
{% bootstrap_form form_professor %}
{% endcomment %}
{% endif %}
{% endif %}
{% endif %}
<br /><br /><br />
<input type="submit" value="Save Changes" class="btn btn-default">
</form>
</div>
{% endblock %}
当我与具有三个配置文件的用户签名并且我呈现配置文件表单时,我得到与呈现的表单相关的此行为。 form_professor和form_executive未呈现
由于这个原因,我认为教授和执行形式实例没有传递给模板,
此问题也已经过验证,因为如果我删除了评论并在我的模板中使用了django-bootstrap3
应用,则无法获得form_professor
和form_executive
个实例
此外,虽然我认为我可以在模板中更好地执行条件逻辑。
这里发生了什么事。 我的想法是可以在一个模板中根据配置文件将配置文件表单呈现给用户。
我非常感谢他们的支持。
<小时/> 的更新
根据下面的@Rohan答案,确实,el ... if
声明是问题的根源。现在表格呈现良好。
我的AccountProfilesView
以这种方式停留:
class AccountProfilesView(LoginRequiredMixin, UpdateView):
# All users can access this view
model = get_user_model()
#success_url = reverse_lazy('dashboard')
template_name = 'accounts/profile_form.html'
fields = '__all__'
def get_context_data(self, **kwargs):
context = super(AccountProfilesView, self).get_context_data(**kwargs)
user = self.request.user
if not self.request.POST:
if user.is_student:
profile = user.get_student_profile()
context['userprofile'] = profile
context['form_student'] = forms.StudentProfileForm()
if user.is_professor:
profile = user.get_professor_profile()
context['userprofile'] = profile
context['form_professor'] = forms.ProfessorProfileForm()
print ("profesor form is", context['form_professor'])
if user.is_executive:
profile = user.get_executive_profile()
context['userprofile'] = profile
context['form_executive'] = forms.ExecutiveProfileForm()
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
context = super(AccountProfilesView, self).post(request, *args, **kwargs)
user = self.request.user
if user.is_student:
context['form_student'] = forms.StudentProfileForm(
self.request.POST)
if user.is_professor:
context['form_professor'] = forms.ProfessorProfileForm(
self.request.POST)
if user.is_executive:
context['form_executive'] = forms.ExecutiveProfileForm(
self.request.POST)
return context
def form_valid(self, form):
context = self.get_context_data(form=form)
user = self.request.user
user = form.save()
if user.is_student:
student = context['form_student'].save(commit=False)
student.user = user
student.save()
if user.is_professor:
professor = context['form_professor'].save(commit=False)
professor.user = user
professor.save()
if user.is_executive:
executive = context['form_executive'].save(commit=False)
executive.user = user
executive.save()
return super(AccountProfilesView, self).form_valid(form)
def get_success_url(self):
return reverse('dashboard')
但是现在,当我想保存三个配置文件的表单部署产品时,我收到此错误消息。
File "/home/bgarcial/workspace/ihost_project/accounts/views.py", line 181, in post
context['form_student'] = forms.StudentProfileForm(self.request.POST)
File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/http/response.py", line 142, in __setitem__
value = self._convert_to_charset(value, 'latin-1', mime_encode=True)
File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/http/response.py", line 115, in _convert_to_charset
raise BadHeaderError("Header values can't contain newlines (got %r)" % value)
django.http.response.BadHeaderError: Header values can't contain newlines (got '<tr><th><label for="id_origin_education_school">Origin education institute:</label></th><td><input id="id_origin_education_school" maxlength="128" name="origin_education_school" type="text" value="Universidad CES, Escuela de Ingeniería" required /></td></tr>\n<tr><th><label for="id_current_education_school">Current education institute:</label></th><td><input id="id_current_education_school" maxlength="128" name="current_education_school" type="text" value="Universidad CES" required /></td></tr>\n<tr><th><label for="id_extra_occupation">Extra occupation:</label></th><td><input id="id_extra_occupation" maxlength="128" name="extra_occupation" type="text" value="Networker" required /></td></tr>')
[08/Apr/2017 16:45:05] "POST /accounts/profile/milena/ HTTP/1.1" 500 108439
当表单要渲染时有一些不方便,我确保用POST方法输入的数据填充这个表单,发生错误,我得到这个屏幕:
答案 0 :(得分:1)
get_context_data
函数中的python代码存在问题。您不应使用if..elif..
添加所需的表单。如果用户拥有所有个人资料,则使用您的代码,代码只会进入第一个if
并仅添加学生个人资料表单。
因此,对于所有类型的配置文件,您应该有单独的if
语句。在这种情况下,对于所有类型,您不需要if
and
{。}}。
所以将代码更改为
if user.is_student:
profile = user.get_student_profile()
context['userprofile'] = profile
context['form_student'] = forms.StudentProfileForm()
#NOTE: no elif, only if
if user.is_professor:
profile = user.get_professor_profile()
context['userprofile'] = profile
context['form_professor'] = forms.ProfessorProfileForm()
print ("profesor form is", context['form_professor'])
if user.is_executive:
profile = user.get_executive_profile()
context['userprofile'] = profile
context['form_executive'] = forms.ExecutiveProfileForm()
# NO need for last if user.is_student and user.is_professor and user.is_executive: