如果对象不存在,django CBV 通用 DetailView 重定向
django CBV generic DetailView redirect if object does not exist
我有一个 DetailView,如果当前登录的用户创建了用户配置文件,它会显示用户配置文件。如果用户没有创建配置文件,我需要一个 else 条件。由于我是 django 和 python 的新手,甚至是 CBV 的新手,我不知道下一步该怎么做。我希望 def get_object() 中有一种方法可以重定向到 UserProfile。
如果没有用户配置文件,则会导致 Related Object DoesNotExist 错误。我如何编写 else 或 except 条件以重定向到 ProfileView(创建配置文件的表单)
PS: UserProfile is to Create a profile, UserProfileView is to View a
created profile, UserProfileUpdate is to Update an existing profile.
虽然PK我还是不想过url
我是django 2.0,python3.6.3
专门寻找如何从 DetailView 方法重定向 except/if 案例
Models.py
class User(AbstractUser):
"""User model."""
username = None
email = models.EmailField(_('email address'), unique=True)
phone = models.CharField(max_length=128, unique=True, null=True,
validators=[validators.RegexValidator(
r'^(?:\+?(\d{2}))?(\d{10})$',
_('Enter a valid phone number. Type without space or special charecter.')
)])
objects = UserManager()
REQUIRED_FIELDS = ['first_name']
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
class UserProfile(models.Model):
"""User Profile"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
country = models.CharField(max_length=128)
state = models.CharField(max_length=128)
city = models.CharField(max_length=128)
landmark = models.CharField(
max_length=128, help_text='Enter a landmark closest to you')
address_line_1 = models.CharField(
max_length=128, help_text='House name/Flat No')
address_line_2 = models.CharField(
max_length=128, help_text='Street Name/No')
address_line_3 = models.CharField(
max_length=128, help_text='Locality Name')
pincode = models.IntegerField()
land_phone = models.CharField(max_length=128, unique=True, null=True,
validators=[validators.RegexValidator(
r'^(?:\+?(\d{4}))\-?(\d{7})$',
_('Enter a valid phone number. Type without space. Format 0400-2012345.')
)])
def __str__(self):
return self.user.email
Views.py
class UserProfileFormView(FormView):
form_class = UserProfileForm
template_name = 'userprofile.html'
success_url = '/'
def form_valid(self, form):
import pdb
pdb.set_trace()
temp_form = form.save(commit=False)
temp_form.user = self.request.user
temp_form.save()
return super().form_valid(form)
def form_invalid(self, form):
response = super().form_invalid(form)
return redirect('users:userprofile')
class UserProfileView(DetailView):
model = UserProfile
context_object_name = 'userprofile'
template_name = 'x.html'
# def dispatch(self, request, *args, **kwargs):
# import pdb; pdb.set_trace()
# if self.request.user.userprofile.pk is not None:
# pass
# else:
# return redirect('users:userprofile')
def get_object(self):
import pdb; pdb.set_trace()
self.object = UserProfile.objects.get(pk=self.request.user.userprofile.pk)
return self.object
# def get_context_data(self, **kwargs):
# import pdb; pdb.set_trace()
# context = kwargs
# context_object_name = 'userprofile'
# context['userprofile'] = UserProfile.objects.get(pk=self.request.user.userprofile.pk)
# if context_object_name:
# return context
# else:
# return redirect('users:userprofile')
class UserProfileUpdate(UpdateView):
model = UserProfile
fields = ('address_line_1', 'address_line_2', 'address_line_3',
'landmark', 'city', 'state', 'country', 'pincode', 'land_phone')
template_name = 'userprofile.html'
success_url = 'home'
class UserProfileView(DetailView):
model = UserProfile
context_object_name = 'userprofile'
template_name = 'x.html'
def get(self, request, *args, **kwargs):
from django.http import Http404
try:
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
except Http404:
# redirect is here
from django.shortcuts import redirect
from django.urls import reverse_lazy
return redirect(reverse('users:userprofile_create'))
所以在互联网上搜索了很多次之后,这是我能想到的最佳答案。希望其他人会觉得这有用,或者有更多知识的人有更好的解决方案。
class UserProfileView(DetailView):
model = UserProfile
context_object_name = 'userprofile'
template_name = 'x.html'
def dispatch(self, request, *args, **kwargs):
try:
self.object = self.request.user.userprofile
except:
return redirect('users:userprofile')
self.get_object()
return super(UserProfileView, self).get(request, *args, **kwargs)
def get_object(self):
self.object = self.request.user.userprofile
return self.object
我在这里所做的(或者说 django 为我所做的)是使用 dispatch。通过使用调度,我能够仅过滤那些具有配置文件的用户以继续获取配置文件或使用 get_object 方法 return UserProfile 对象。如果用户没有配置文件,则 dispatch 方法中的 except 条件会将用户重定向到配置文件创建页面。如果用户有配置文件,则调度调用(覆盖。我不确定使用哪个术语)get_object 方法来获取 existing 对象。总结一下,get_object 方法可以 只有 return 个对象作为响应 。因此,我尝试重定向的尝试(代码的注释部分)无法正常工作,因为 django 不允许这样做。如果我的解释有任何错误,请指出我的缺点
我知道你的问题很老了,但没有人真正回答过,所以我想我会的。
我建议在您的用户模型上创建一个方法来检查是否有用户配置文件,例如:
def has_profile(self):
return hasattr(self, 'userprofile')
'hasattr' 将 return 为真或假。
现在在调度中你可以做
def dispatch(self, request, *args, **kwargs):
if not self.request.user.has_profile():
return redirect('users:userprofile')
return super().dispatch(request, *args, **kwargs)
我有一个 DetailView,如果当前登录的用户创建了用户配置文件,它会显示用户配置文件。如果用户没有创建配置文件,我需要一个 else 条件。由于我是 django 和 python 的新手,甚至是 CBV 的新手,我不知道下一步该怎么做。我希望 def get_object() 中有一种方法可以重定向到 UserProfile。 如果没有用户配置文件,则会导致 Related Object DoesNotExist 错误。我如何编写 else 或 except 条件以重定向到 ProfileView(创建配置文件的表单)
PS: UserProfile is to Create a profile, UserProfileView is to View a created profile, UserProfileUpdate is to Update an existing profile.
虽然PK我还是不想过url
我是django 2.0,python3.6.3
专门寻找如何从 DetailView 方法重定向 except/if 案例
Models.py
class User(AbstractUser):
"""User model."""
username = None
email = models.EmailField(_('email address'), unique=True)
phone = models.CharField(max_length=128, unique=True, null=True,
validators=[validators.RegexValidator(
r'^(?:\+?(\d{2}))?(\d{10})$',
_('Enter a valid phone number. Type without space or special charecter.')
)])
objects = UserManager()
REQUIRED_FIELDS = ['first_name']
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
class UserProfile(models.Model):
"""User Profile"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
country = models.CharField(max_length=128)
state = models.CharField(max_length=128)
city = models.CharField(max_length=128)
landmark = models.CharField(
max_length=128, help_text='Enter a landmark closest to you')
address_line_1 = models.CharField(
max_length=128, help_text='House name/Flat No')
address_line_2 = models.CharField(
max_length=128, help_text='Street Name/No')
address_line_3 = models.CharField(
max_length=128, help_text='Locality Name')
pincode = models.IntegerField()
land_phone = models.CharField(max_length=128, unique=True, null=True,
validators=[validators.RegexValidator(
r'^(?:\+?(\d{4}))\-?(\d{7})$',
_('Enter a valid phone number. Type without space. Format 0400-2012345.')
)])
def __str__(self):
return self.user.email
Views.py
class UserProfileFormView(FormView):
form_class = UserProfileForm
template_name = 'userprofile.html'
success_url = '/'
def form_valid(self, form):
import pdb
pdb.set_trace()
temp_form = form.save(commit=False)
temp_form.user = self.request.user
temp_form.save()
return super().form_valid(form)
def form_invalid(self, form):
response = super().form_invalid(form)
return redirect('users:userprofile')
class UserProfileView(DetailView):
model = UserProfile
context_object_name = 'userprofile'
template_name = 'x.html'
# def dispatch(self, request, *args, **kwargs):
# import pdb; pdb.set_trace()
# if self.request.user.userprofile.pk is not None:
# pass
# else:
# return redirect('users:userprofile')
def get_object(self):
import pdb; pdb.set_trace()
self.object = UserProfile.objects.get(pk=self.request.user.userprofile.pk)
return self.object
# def get_context_data(self, **kwargs):
# import pdb; pdb.set_trace()
# context = kwargs
# context_object_name = 'userprofile'
# context['userprofile'] = UserProfile.objects.get(pk=self.request.user.userprofile.pk)
# if context_object_name:
# return context
# else:
# return redirect('users:userprofile')
class UserProfileUpdate(UpdateView):
model = UserProfile
fields = ('address_line_1', 'address_line_2', 'address_line_3',
'landmark', 'city', 'state', 'country', 'pincode', 'land_phone')
template_name = 'userprofile.html'
success_url = 'home'
class UserProfileView(DetailView):
model = UserProfile
context_object_name = 'userprofile'
template_name = 'x.html'
def get(self, request, *args, **kwargs):
from django.http import Http404
try:
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
except Http404:
# redirect is here
from django.shortcuts import redirect
from django.urls import reverse_lazy
return redirect(reverse('users:userprofile_create'))
所以在互联网上搜索了很多次之后,这是我能想到的最佳答案。希望其他人会觉得这有用,或者有更多知识的人有更好的解决方案。
class UserProfileView(DetailView):
model = UserProfile
context_object_name = 'userprofile'
template_name = 'x.html'
def dispatch(self, request, *args, **kwargs):
try:
self.object = self.request.user.userprofile
except:
return redirect('users:userprofile')
self.get_object()
return super(UserProfileView, self).get(request, *args, **kwargs)
def get_object(self):
self.object = self.request.user.userprofile
return self.object
我在这里所做的(或者说 django 为我所做的)是使用 dispatch。通过使用调度,我能够仅过滤那些具有配置文件的用户以继续获取配置文件或使用 get_object 方法 return UserProfile 对象。如果用户没有配置文件,则 dispatch 方法中的 except 条件会将用户重定向到配置文件创建页面。如果用户有配置文件,则调度调用(覆盖。我不确定使用哪个术语)get_object 方法来获取 existing 对象。总结一下,get_object 方法可以 只有 return 个对象作为响应 。因此,我尝试重定向的尝试(代码的注释部分)无法正常工作,因为 django 不允许这样做。如果我的解释有任何错误,请指出我的缺点
我知道你的问题很老了,但没有人真正回答过,所以我想我会的。
我建议在您的用户模型上创建一个方法来检查是否有用户配置文件,例如:
def has_profile(self):
return hasattr(self, 'userprofile')
'hasattr' 将 return 为真或假。 现在在调度中你可以做
def dispatch(self, request, *args, **kwargs):
if not self.request.user.has_profile():
return redirect('users:userprofile')
return super().dispatch(request, *args, **kwargs)