Django UpdateView disable some fields - django

I have made a class view inheriting UpdateView. I have specified the fields and models from which the forms should be built. Now say if i have a field email, then I want to disable it in the form. I have no clues as to how it can be done.
class UserUpdate(UpdateView):
model = Users
fields = ['email', 'first_name', 'last_name', 'birth_date']
template_name = 'users_update_form.html'
success_url = '/index/'

To hide it:
class UserUpdate(UpdateView):
model = Users
fields = ['first_name', 'last_name', 'birth_date']
template_name = 'users_update_form.html'
In this case there is no need to create a separate Form class - as this is handled by the UpdateView.
To make the fiel readonly:
class UserForm(forms.ModelForm):
class Meta:
model = Users
fields = ['email', 'first_name', 'last_name', 'birth_date']
email = forms.CharField(widget=forms.TextInput(attrs={'readonly':'readonly'}))
def clean_email(self):
return self.initial['email']
class UserUpdate(UpdateView):
model = Users
form_class = UserForm
Note for Django 1.9
Django 1.9 has a disabled option built in. Using this allows you to skip the additional clean method.
class UserForm(forms.ModelForm):
class Meta:
model = Users
fields = ['email', 'first_name', 'last_name', 'birth_date']
email = forms.CharField(disabled=True)

Define a UserForm with exclude fields which you don't want to show in the form
class UserForm(forms.ModelForm):
class Meta:
model = Users
exclude = ('email',) # add fields to disable it in the form
If you want to make field readonly in > django 1.9
use disabled
class UserForm(forms.ModelForm):
email = forms.CharField(disabled=True)
class Meta:
model = Users
fields = ['email', 'first_name', 'last_name', 'birth_date']
Then specify form in view.
class UserUpdate(UpdateView):
model = Users
form_class = UserForm
....

Related

Get the username with django profileserializer

I developed api with django. I created a code structure like below.
How do I get the user's first_name and last_name in class ProfileSerializer?
that is, with ProfileSerializer, I want to get information such as the user's name, surname, id number
``
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import validate_password
from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework import serializers
from account.models import Profile
class ProfileSerializer(ModelSerializer):
class Meta:
model = Profile
fields = ('id', 'userKey', 'phone', 'email', 'address', 'userState')
class UserSerializer(ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ('id', 'first_name', 'last_name', 'profile')
def update(self, instance, validated_data):
profile = validated_data.pop('profile')
profile_serializer = ProfileSerializer(instance=instance.profile, data=profile)
profile_serializer.is_valid(raise_exception=True)
profile_serializer.save()
return super(UserSerializer, self).update(instance, validated_data)
``
Simply define serializers.CharField() as,
class ProfileSerializer(ModelSerializer):
first_name = serializers.CharField(source='user.first_name', read_only=True)
last_name = serializers.CharField(source='user.last_name' read_only=True)
class Meta:
model = Profile
fields = ('id', 'userKey', 'phone', 'email',
'address', 'userState', 'first_name', 'last_name')
Just change your serializer like this
class ProfileSerializer(ModelSerializer):
class Meta:
model = Profile
fields = ('id', 'userKey', 'phone', 'email', 'address', 'userState')
def to_representation(self, instance):
data = super().to_representation(instance)
data.update({'username': instance.userKey.username, 'first_name': instance.userKey.first_name, 'last_name': instance.userKey.last_name})
return data

Display custom form in Django admin

I created a custom user model with country in it:
models.py
class CustomUser(AbstractUser):
country = models.CharField(max_length=50, default="None")
Then added custom forms with form field country which is a ChoiceField and shows all the countries:
forms.py
class CustomUserCreationForm(UserCreationForm):
country = forms.ChoiceField(choices=sorted(COUNTRIES.items()), label="Country")
class Meta(UserCreationForm):
model = CustomUser
fields = '__all__'
class CustomUserChangeForm(UserChangeForm):
country = forms.ChoiceField(choices=sorted(COUNTRIES.items()), label="Country")
class Meta(UserChangeForm):
model = CustomUser
fields = '__all__'
Then I registered it in the admin with:
admin.py
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username', 'is_staff',]
admin.site.register(CustomUser, CustomUserAdmin)
It registered and everything is working fine, I am able to save the model with Django shell and programmatically, but I am not able to display it in the admin console. When I try to try to create a new user from the admin, I just see three fields - username, password and password confirmation.
Do I have to extend the admin template for this new field to show up?
To do this you will have to add_fieldsets under CustomUserAdmin in admin.py:
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username', 'is_staff',]
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2', 'country'),
}),
)
admin.site.register(CustomUser, CustomUserAdmin)
In Django 4.1+, the add_form option on a ModelAdmin has been removed. You should instead use the get_form() argument, like follows:
···python
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
def get_form(self, request, obj=None, change=False, **kwargs):
if not change and not obj:
self.form = self.add_form
return super().get_form(request, obj, **kwargs)
···

Django UserCreationForm extension

can i add fields like address,city,state,country,pincode and security question and answer to the extension of UserCreationForm that currently contains username,email,password1 and password2. if yes then please illustrate how?
forms.py
class UserCreationForm(UserCreationForm):
email = EmailField(label=_("Email address"), required=True,
help_text=_("Required."))
city= forms.CharField(label= _("City"),max_length=20, required=True)
state= forms.CharField(label= _("State"),max_length=20, required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2","city","state")
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
user.city = self.cleaned_data["city"]
user.state = self.cleaned_data["state"]
if commit:
user.save()
return user
Yes just do like you did with email:
class UserCreationForm:
a_field = WhateverField(whatever='whatever'...)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
The field is now added in your form.
currently you are extending UserCreationForm class if you have other fields in user model then you can use forms.ModelForm and just mention other fields.
for example
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username','name', 'email', 'phone',
'address','city','state', 'first_time']
if you want to use custom form then.
class UserForm(forms.Form):
name = forms.CharField(label= _("Name"))
address = forms.CharField(label=_("Address"))
etc.

Django AbstractUser doesn't show model

I'm a django beginner and i want to add a booleanfield to AbstractUser, but it's not showing the booleanfield in the admin.
models.py
class CustomUser(AbstractUser):
selected = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['selected',]
def __str__(self):
return self.username
admin.py
class MyUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = CustomUser
class UserAdmin(BaseUserAdmin):
form = MyUserChangeForm
list_display = ('username', 'first_name', 'last_name', 'email', 'is_staff', 'selected')
admin.site.register(CustomUser, UserAdmin)
settings.py
AUTH_USER_MODEL = 'football_app.CustomUser'
in admin.py file change
class UserAdmin(BaseUserAdmin): to class UserAdmin(CustomUser):
EDIT: update your class like this
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'first_name', 'last_name', 'email', 'is_staff', 'selected')
class Meta:
model = CustomUser
You need to unregister current User admin first.
admin.site.unregister(User)
admin.site.register(CustomUser, UserAdmin)

How to implement serializing for nested objects

Had implemented a basic authentication system using function based views in django.
Trying to upgrade it to class based views.
Creating a UserProfile by inheriting from a django User model.
Need to serialize UserProfile and return to client side
User model :
from django.contrib.auth.models import User
UserProfile model :
class UserProfile(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
profile_picture = models.ImageField(upload_to='documents', blank=True)
def __str__(self):
return self.user.username
UserSerializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username','password', 'first_name', 'last_name', 'email',)
write_only_fields = ('password',)
read_only_fields = ('is_staff', 'is_superuser', 'is_active', 'date_joined',)
def restore_object(self, attrs, instance=None):
user = super(UserSerializer, self).restore_object(attrs, instance)
user.set_password(attrs['password'])
return user
UserProfileSerializer:
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = UserProfile
fields = ('id','user','profile_picture',)
views.py:
class AuthView(APIView):
authentication_classes = (BasicAuthentication,)
def post(self, request, *args, **kwargs):
login(request, request.user)
content={ 'user':UserProfileSerializer(request.user).data,'token':csrf.get_token(request)}
return Response(content)
UserProfileSerializer(request.user).data in views.py is not working.
but instead if i use:
UserSerializer(request.user).data, it gives me result(as expected) :
{'first_name': '', 'username': 'admin', 'email': 'a#a.com', 'last_name': '', 'password': 'pbkdf2_'}
But i also want additional attributes to the user also serialized like profile_picture, hence something like
UserProfileSerializer(request.user).data
should work for me.
Questions:
Is it possible to serialize a model containing FileField ?
How to serialize a nested object and return its data ?
Kinda beginner here.
yes it is possible to serialize a FileField. The problem is that your profile serializer needs a UserProfile model and not a User model. Try this:
content={ 'user':UserProfileSerializer(request.user.user_profile).data,'token':csrf.get_token(request)}