I cannot update using an inline form.
I thought it was possible before, but it wasn't.
I'm trying to solve it, but it doesn't work.
I added.
I will post any other necessary items.
"Id
This field is required.
user
A Profile with this User already exists.
"
I got an error.
#view
class UserEdit(generic.UpdateView):
model = User
form_class = forms.UserUpdateForm
template_name = 'accounts/accounts_edit.html'
success_url = reverse_lazy('person:myaccount')
def get_object(self):
return get_object_or_404(User, pk=self.request.user.user_id)
#model
class User(AbstractBaseUser, PermissionsMixin):
username_validator = UnicodeUsernameValidator()
user_id = models.UUIDField(default=uuid_lib.uuid4,
primary_key=True, editable=False)
username = models.CharField(_('username'), unique=True, max_length=50,validators=[username_validator],error_messages={
'unique': _("A user with that username already exists."),
},)
class profile(models.Model):
image = models.ImageField(upload_to='profile/',default='profile/default.jpg')
first_name = models.CharField(_('first name'), max_length=30, blank=True,null=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True,null=True)
birthday = models.DateField(_('birthday',),null=True)
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,)
#form
class ProfileUpdateForm(BaseModelForm):
class Meta:
model = profile
fields = ('first_name','last_name','birthday',)
ProfileFormSet = inlineformset_factory(User,profile,form=ProfileUpdateForm,extra=0)
class UserUpdateForm(mixins.ModelFormWithFormSetMixin,BaseModelForm):
formset_class = ProfileFormSet
class Meta:
model = User
fields = ('username','email',)
#mixin
class ModelFormWithFormSetMixin:
def __init__(self, *args, **kwargs):
super(ModelFormWithFormSetMixin, self).__init__(*args, **kwargs)
self.formset = self.formset_class(
instance=self.instance,
data=self.data if self.is_bound else None,
)
def is_valid(self):
return super(ModelFormWithFormSetMixin, self).is_valid() and self.formset.is_valid()
def save(self, commit=True):
saved_instance = super(ModelFormWithFormSetMixin, self).save(commit)
self.formset.save(commit)
return saved_instance
Related
I have two forms (OwnerCreateForm, EmployeesCreateForm) and 3 models (Profile, Company and Owner). when the owner signs up, it creates the company and its own User object. after owner login, you can create employees.
Have the Owner connect to the profile and associate it with the company
I need to associate the owning company to the employees.
That each company manages its users, that they see the same thing
Here are the details I'm using:
MODELS
class Profile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return '{} Profile'.format(self.user)
class Owner(models.Model):
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
def __str__(self):
return '{} Owner'.format(self.profile)
class Tienda(models.Model):
dueƱo = models.ForeignKey(Owner, null=True, on_delete=models.CASCADE)
nombre_tienda = models.CharField(verbose_name='Nombre de la Tienda', max_length=120)
direccion = models.CharField(verbose_name='Su Direccion', max_length=160)
phone = models.CharField(max_length=11, null=True)
businessemail = models.EmailField(unique = True, verbose_name='Su email')
def __str__(self):
return self.nombre_tienda
class Employee(models.Model):
STATUS = (
('Admin', 'Admin'),
('Gerente', 'Gerente'),
('Validador', 'Validador')
)
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
role = models.CharField(choices=STATUS, max_length=16)
tienda = models.ForeignKey(Tienda, null=True, on_delete=models.CASCADE)
def __str__(self):
texto = "{0} ({1}) {2}"
return texto.format(self.tienda, self.role, self.role)
FORMS
class TiendaForm(ModelForm):
class Meta:
model = Tienda
fields = ('nombre_tienda', 'direccion', 'businessemail')
class OwnerCreateForm(UserCreationForm):
class Meta:
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
model = User
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Display Name'
self.fields['email'].label = "Email Address"
class EmployeesCreateForm(UserCreationForm):
is_admin = forms.BooleanField(required=False)
is_manager = forms.BooleanField(required=False)
is_systemAdmin = forms.BooleanField(required=False)
class Meta:
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
model = User
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Display Name'
self.fields['email'].label = "Email Address"
VIEWS
def registroOwner(request):
if request.method == "POST":
form = OwnerCreateForm(request.POST)
tienda = TiendaForm(request.POST)
if form.is_valid() and tienda.is_valid():
tienda.save()
form.save()
messages.success(request, f'Tu cuenta ha sido creada!')
return redirect('login')
else:
form = OwnerCreateForm()
tienda = TiendaForm()
context = {
'title': 'Sign up Owner',
'form': form,
'tienda': tienda
}
return render(request, "accounts/signup.html", context)
I am facing one issue with django forms
Here is my model :
class User(models.Model):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class UserProfile(AuditFields):
user = models.ForeignKey(User, on_delete=models.CASCADE)
designation = models.CharField(max_length=200, blank=True)
contact_number = models.CharField(max_length=20, blank=True)
team = models.CharField(max_length=200, blank=True)
manager = models.CharField(max_length=200, blank=True)
joining_date = models.DateField(default=datetime.now)
I need to create a form for editing profile details of the current user
This is my form. But it is a model Form so only getting the detauls from the User Profile table only
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
exclude = ['user']
How can I get first_name , last_name from User table and save it
Just add the fields as a CharField in form, and use cleaned_data attribute to fetch the data and save it:
class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(max_length=30,required=True)
last_name = forms.CharField(max_length=30,required=True)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance:
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
class Meta:
model = UserProfile
exclude = ['user']
def save(self, commit=False):
instance = super().save(commit=True)
user = instance.user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
return instance
After creating a custom user model in my app, I have a studentProfile that inherits from the user model, which also contains avatar, semester, and dept_name. which works fine. However, when I was trying to display this studentProfile data using django-tables2, all rows keeps showing "-" and the ID been captured is from user model instead of studentProfile.
The weirdiest thing is i can get all the values from user model
correctly even when studentProfile is my table model for
django-tables2
I don't know what I am doing wrongly. Any help is really appreciated
my model definitions are as follow
class DepartmentData(models.Model):
fid = models.ForeignKey(FacultyData, on_delete=models.CASCADE)
dept_name = models.CharField(max_length=50)
created_on = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.dept_name
class User(AbstractBaseUser):
# add additional fields here
user_id = models.CharField(max_length=15, unique=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
active = models.BooleanField(default=True)# can login
staff = models.BooleanField(default=False) # staff user non superuser
admin = models.BooleanField(default=False) # superuser
USER_TYPE_CHOICES = (
(1, 'student'),
(2, 'lecturer'),
(3, 'bursary'),
(4, 'system'),
(5, 'admin'),
)
user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES)
USERNAME_FIELD = 'user_id'
REQUIRED_FIELDS = ['first_name', 'last_name', 'user_type']
objects = UserManager()
def __str__(self):
return self.user_id
def get_full_name(self):
return self.first_name + " " + self.last_name
def get_user_type(self):
return self.user_type
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
class StudentProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
semester = models.ForeignKey(SemesterData, on_delete=models.SET_NULL, null=True)
dept_name = models.ForeignKey(DepartmentData, on_delete=models.SET_NULL, null=True)
avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
def __str__(self):
return self.user.first_name
class SemesterData(models.Model):
sid = models.ForeignKey(SessionData, on_delete=models.CASCADE)
semester_name = models.CharField(max_length=50)
def __str__(self):
return self.semester_name
def current(self):
if SettingsData.objects.all().count():
st = SettingsData.objects.get(id=1)
if self.id == st.current_id:
return "Current Session-Semester"
else:
return format_html('{}', reverse('system:current_session_semester', args=[self.id]),
'Set Current')
else:
return format_html('{}', reverse('system:current_session_semester', args=[self.id]),
'Set Current')
here is my table.py
class StudentTable(tables.Table):
user_id = tables.Column(attrs = {'th': {'class': 'danger'}})
first_name = tables.Column(attrs = {'th': {'class': 'danger'}})
last_name = tables.Column(attrs = {'th': {'class': 'danger'}})
avatar = tables.Column(accessor ="user", verbose_name = "ass" )
active = tables.Column(attrs = {'th': {'class': 'danger'}})
last_login = tables.Column(attrs = {'th': {'class': 'danger'}})
edit_Action = tables.LinkColumn('system:semester_edit', text='Edit', args=[A('pk')],attrs={'a':{'class':'btn btn-info btn-sm'}, 'td':{'align': 'center'}, 'th': {'class': 'danger'}}, orderable=False)
class Meta:
model = StudentProfile
attrs = {'class':'table table-hover table-bordered table-responsive'}
sequence = ('user_id', 'first_name', 'last_name', 'avatar')
exclude = {'id', 'user', 'password', 'staff', 'admin'}
empty_text = _("There are no students yet")
template_name = 'django_tables2/bootstrap4.html'
I would love to get the department_name, semester_name as well as fields in the studentProfile which is serving as my table model
You are seeing empty values for all fields with your current configuration because you're trying to access fields user_id, first_name and last_name which are not fields of the StudentProfile model, but rather fields of the User model (to which StudentProfile is related by user field).
That being said, you should access those fields via the user relation, something like this:
class StudentTable(tables.Table):
user_id = tables.Column(accessor='user.user_id', ...)
first_name = tables.Column(accessor='user.first_name', ...)
last_name = tables.Column(accessor='user.last_name', ...)
...
As far as the DepartmentData and SemesterData relations go, I'm not sure why aren't they displayed by default, since they are fields of the StudentProfile model, and they aren't excluded via the exclude property on the Meta. You can maybe try to explicitly list them in the fields property and see if that helps.
I'm trying to first access the users table via the user foreign key present in userinformations models and later override the RetriveUpdateDestroy API view's destroy method to change the status of the user to inactive instead of deleting them. I can't seem to access the is-active field of the in built User database.
views.py
class UserUpdateApiView(RetrieveUpdateDestroyAPIView):
queryset = UserInformation.objects.all()
serializer_class = UserInformationUpdateSerializer
lookup_field = 'pk'
lookup_url_kwarg = 'id'
def destroy(self, request, *args, **kwargs):
try:
user = User.objects.get(pk=self.kwargs["id"])
deleteStatusVal = False
user.is_active = deleteStatusVal
user.save()
return Response(UserSerializer(user).data)
except:
return Response("Nope")
serializers.py
class UserSerializer(ModelSerializer):
password = serializers.CharField(style={'input_type': 'password'}, write_only=True)
email = serializers.EmailField(validators=[required])
class Meta:
model = User
fields = ['username', 'email', 'password', 'is_active']
extra_kwargs = {'password': {'write_only': True},
'is_active': {'read_only': True}}
def validate(self, data):
email = data.get('email', None)
user = User.objects.filter(email=email).distinct()
if user.exists():
raise ValidationError("That email is already registered!")
return data
class UserInformationUpdateSerializer(ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = UserInformation
fields = ['user', 'first_name', 'middle_name', 'last_name', 'phone', 'date_of_birth']
models.py
class UserInformation(BaseModel):
user = models.OneToOneField(User, related_name='user_id')
first_name = models.CharField(max_length=45)
middle_name = models.CharField(max_length=45, null=True)
last_name = models.CharField(max_length=45)
vendor = models.BooleanField(default=False)
phone = models.CharField(max_length=100, validators=[
RegexValidator(regex=r'^\+?8801?\d{9}$', message="Phone number must be entered in the format: '+8801*********'")
], blank=False, unique=True)
date_of_birth = models.DateField()
confirmation_token = models.CharField(max_length=45, null=True)
confirmation_exp = models.DateTimeField(null=True)
pw_reminder_token = models.CharField(max_length=45, null=True)
pw_reminder_exp = models.DateTimeField(null=True)
profile_pic = models.ImageField(blank=True, null=True, upload_to='profile_images/', default='Images/none/no_images.jpg')
cover_photo = models.ImageField(blank=True, null=True, upload_to='cover_images/', default='Images/none/no_images.jpg')
thumbnail_pic = models.ImageField(blank=True, null=True, upload_to='thumbnail_images/', default='Images/none/no_images.jpg')
phone_verified = models.BooleanField(default=False)
email_verified = models.BooleanField(default=False)
reward_points = models.IntegerField(null=False)
ref_code = models.CharField(null=True, max_length=10)
def __str__(self):
return self.user.username
def delete(self, *args, **kwargs):
self.user.delete()
super(UserInformation, self).delete(*args, **kwargs)
If you want to make User as in active while keeping the UserInformation object and Userobject un-deleted in database, you can do something like this:
def destroy(self, request, *args, **kwargs):
user = self.get_object().user
user.is_active = False
user.save()
return Response(UserInformationUpdateSerializer(self.get_object()).data)
You have 'is_active': {'read_only': True}}.
Also,
# this seems redundant
def delete(self, *args, **kwargs):
self.user.delete()
super(UserInformation, self).delete(*args, **kwargs)
I've "extended" Django's contrib.auth.models "user" like:
class UserProfile(models.Model):
user = models.ForeignKey(User, related_name = 'profile')
date_of_birth = models.DateField(blank=True, null=True)
avatar = models.ImageField(upload_to=get_avatar_path, null=True, blank=True)
friends = models.ManyToManyField(User, related_name = 'user_friends', blank=True, null=True)
bio = models.TextField(null=True, blank=True)
I'd want the user to be able to update email from UserChangeForm, something like this:
forms.py
class UserUpdateForm(UserChangeForm):
email = forms.EmailField()
def __init__(self, *args, **kwargs):
super(UserUpdateForm, self).__init__(*args, **kwargs)
self.fields.pop('username')
self.fields['email'].initial = self.instance.user.email
class Meta:
exclude = ('friends', 'username', 'password1', 'password2')
model = UserProfile
Except that one doesn't save the email.
I thought of trying to access request.post data from post_save signal so I could set user's new email there, but couldn't get that one working.
Any help is appreciated, thanks.
You need to override the form's save method as well:
class UserUpdateForm(UserChangeForm):
email = forms.EmailField()
class Meta:
exclude = ('friends', 'username', 'password1', 'password2')
model = UserProfile
def __init__(self, *args, **kwargs):
super(UserUpdateForm, self).__init__(*args, **kwargs)
self.fields.pop('username')
self.fields['email'].initial = self.instance.user.email
def save(self, commit=True):
self.instance.user.email = self.cleaned_data['email']
if commit:
self.instance.user.save()
super(UserUpdateForm, self).save(commit)