I have a DetailView which displays userprofile if the current logged in user has a userprofile created. If the user does not have a profile created, i need an else condition. Since im new to django and python, and even newer to CBV, i cannot figure out my next step. I'm hoping there is a way in def get_object() to redirect to UserProfile. Without a userprofile present it results in Related Object DoesNotExist error. How can i write an else or except condition to redirect to ProfileView (form to create profile)
PS: UserProfile is to Create a profile, UserProfileView is to View a created profile, UserProfileUpdate is to Update an existing profile.
I prefer not to pass PK though url
I am django 2.0, python 3.6.3
specifically looking for how to redirect an except/if case from DetailView methods
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'
So after quite a few searching over the internet this is the best answer i could come up with. Hope someone else will find this useful, or some one with better knowledge has a more optimal solution.
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
What i did here (or rather what django does for me ) is use dispatch. By using dispatch i was able to filter only those users with profiles to proceed to get the profile or return a UserProfile object using get_object method. If a user does not have profile then the except condition in dispatch method redirects the user to profile creation page. If a user has profile then dispatch calls (overide. i am not sure which term to use) get_object method to get the existing object. Well to sum it up, get_object method can only return objects as response. So my attempts (commented section of code) in trying to redirect could not work as django wont allow it. If any of my explanation is wrong, please do point out my drawbacks