naruto naruto - 27 days ago 7
Python Question

'User' object has no attribute 'leave'

I am making a leave application module and I got "User has no attribute" errors

models.py

from django.db import models
from django.contrib.auth.models import User;
from django.db.models.signals import post_save
from django.dispatch import receiver
LEAVE_CHIOCE = (
('casual', 'Casual Leave'),
('vacation', 'Vacation Leave'),
('commuted', 'Commuted Leave'),
('special_casual', 'Special Casual Leave'),
('restricted', 'Restricted Leave'),
('st

ation', 'Station Leave'),
)

APPLICATION_STATUSES = (

('accepted', 'Accepted'),
('rejected', 'Rejected'),
('processing', 'Being Processed')

)
class Leave(models.Model):
user = models.OneToOneField(User,related_name='applied_for', on_delete=models.CASCADE);
leave_type = models.CharField(max_length=20, choices=LEAVE_CHIOCE);
applied_time = models.DateTimeField(auto_now = True);
start_date = models.DateField();
end_date = models.DateField();
purpose = models.CharField(max_length=500, blank=True);
leave_address = models.CharField(max_length=100, blank=True);
processing_status = models.CharField(max_length=20, choices=APPLICATION_STATUSES);

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Leave.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.leave.save()


forms.py

from django import forms;
from . models import Leave, ApplicationRequest, RemainingLeaves;
from django.contrib.auth.models import User;
from django.contrib.auth.forms import UserCreationForm;
from datetime import datetime


class UserForm(forms.ModelForm):
class Meta:
model = User;
fields = ('username', 'first_name', 'last_name', 'email');

class LeaveForm(forms.ModelForm):
model = Leave;
class Meta:
fields = ( 'leave_type', 'start_date', 'end_date', 'purpose', 'leave_address');


view.py

from __future__ import unicode_literals
from django.contrib.auth.models import PermissionsMixin
from django.shortcuts import render
from django.http import HttpResponse;
from . models import Leave, ApplicationRequest, RemainingLeaves;
from django.contrib.auth.decorators import login_required;
from . forms import LeaveForm, UserForm;
from django.db import transaction
from django.contrib.auth.models import User
import os;


# Create your views here.
@login_required(login_url='/login')
@transaction.atomic
def getLeaveTemplate(request):
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)));
if request.method == 'POST':
user_form = UserForm(request.POST, instance=request.user);
leave_form = LeaveFor[enter image description here][1]m(request.POST, instance=request.user.leave)

if user_form.is_valid() and leave_form.is_valid():
user_form.save();
leave_form.save();
return HttpResponse("Thanksss");
else:
user_form = UserForm(instance=request.user);
leave_form = LeaveForm(instance=request.user.leave);
return render(request, BASE_DIR+"/templates/pages/leaveform.html", {'user_form':user_form});

Answer Source

related_name described in Django documentation:

The name to use for the relation from the related object back to this one.

You are declaring the related_name to be applied_for on the following line:

user = models.OneToOneField(User, related_name='applied_for', on_delete=models.CASCADE)

This means that a Leave object will have the property user which is used to get the related User object. To go from a User object to the related Leave object the property [related_name] is added. This is in your case applied_for. To remove your errors simply change each request.user.leave to request.user.applied_for.

In order to change the applied_for property to leave you can change the definition to the following:

user = models.OneToOneField(User, related_name='leave', on_delete=models.CASCADE)

But the related_name is an optional argument and it has a useful default value:

If you do not specify the related_name argument for the OneToOneField, Django will use the lower-case name of the current model as default value.

So in your case not supplying a default value will add the property leave to User objects

# in model
user = models.OneToOneField(User, on_delete=models.CASCADE)

# in view
request.user.leave