Home > Back-end >  django If don't have a model, Redirect to createview. If there is, I would like to do it in det
django If don't have a model, Redirect to createview. If there is, I would like to do it in det

Time:08-10

class KcalDetailView(DetailView):
    model = User
    context_object_name = 'target_kcal'
    template_name = 'kcalculatorapp/detail.html'

    def dispatch(self, request, *args, **kwargs):
        if not self.request.user.kcal:
            return HttpResponseRedirect(reverse('kcalculatorapp:create'))
        return super(KcalDetailView, self).dispatch(request, *args, **kwargs)

model.py

class Kcal(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='kcal', null=True)
    height = models.PositiveIntegerField(default='',  null=False , verbose_name='height')
    weight = models.PositiveIntegerField(default='',  null=False, verbose_name='weight')
    age = models.PositiveIntegerField(default='',  null=False, verbose_name='age')
    created_at = models.DateField(auto_now_add=True, null=True)

If you go into the detail view,

User has no kcal. error

That's what it says What should I do?

enter image description here

CodePudding user response:

Your code would work if you would have kcal field on User linking your User to Kcal. If you are trying to get object with one to one relation by related name in Django and object does not exist, ObjectDoesNotExist exception is raised. What you should do is embed your redirect in try ... except... block like that:

try:
    self.request.user.kcal:
except ObjectDoesNotExist:
    return HttpResponseRedirect(reverse('kcalculatorapp:create'))

Of course you could do Kcal.ObjectDoesNotExist but i don't know your project structure if it would not cause circle import error

CodePudding user response:

Firstly, you should override the get method instead of the dispatch method and use getattr to check for a Kcal relation.

class KcalDetailView(DetailView):
    ...

    def get(self, request, *args, **kwargs):
        if not getattr(self.request.user, 'kcal', None):
            return HttpResponseRedirect(reverse('kcalculatorapp:create'))
        return super().get(request, *args, **kwargs)

And since you are relying on authentication rather than url kwargs to determine the object to return, you need to override the get_object method as well.

class KcalDetailView(DetailView):
    ...

    def get_object(self, queryset=None):
        return self.request.user.kcal

So your final view should look something like this:

class KcalDetailView(DetailView):
    context_object_name = 'target_kcal'
    template_name = 'kcalculatorapp/detail.html'

    def get_object(self, queryset=None):
        return self.request.user.kcal

    def get(self, request, *args, **kwargs):
        if not getattr(self.request.user, 'kcal', None):
            return HttpResponseRedirect(reverse('kcalculatorapp:create'))
        return super().get(request, *args, **kwargs)
  • Related