class ApplicationForm(BaseForm):
class Meta:
model = Application
fields = ['referencenumber', 'name', 'description', 'owner']
I have the above form from models.py. However I want to put labels on the form that are different than the verbose_name of models.py. I can't edit models.py since we are too far into development.
Any way to do this in forms?
Labels are verbose_names of the model you can change it. This will help you:
Solution #1
class ApplicationForm(BaseForm):
class Meta:
model = Application
fields = ['referencenumber', 'name', 'description', 'owner']
def __init__(self, *args, **kwargs):
super(ApplicationForm, self).__init__(*args, **kwargs)
self.fields['referencenumber'].label = "reference number"
self.fields['name'].label = "name"
Solution #2
class ApplicationForm(BaseForm):
class Meta:
model = Application
fields = ['referencenumber', 'name', 'description', 'owner']
labels = {
'referencenumber': 'referencenumber',
'name': 'name',
}
Related
I want to Customize my form input in forms.py. I am using crispy form. I want to input 'phone number' with specific length instead of 'username' and also that should be in a specific Language(not English).
I also want to input name_ban,fathers_name_bangla,mothers_name_bangla fields in only a specific language text(bengali).How can I do that?
How can I implement such a condition in my forms.py?
codes are given below.
forms.py
from django.forms import ModelForm
from .models import *
from django import forms
from django.contrib.auth.forms import UserCreationForm
class Add_Applicant(ModelForm):
class Meta:
model = Applicant
fields =[
"course", "session", "name_ban", "name_eng",
"fathers_name_bangla", "fathers_name",
"mothers_name_bangla", "mothers_name",
"marital_status", "present_address",
"village", "district",
"sub_district", "ps",
"post_office", "date_of_birth",
"religion", "nid_BC",
"education", "phone", "Guardian_phone",
"picture"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['sub_district'].queryset = Sub_district.objects.none()
if 'district' in self.data:
try:
district_id = int(self.data.get('district'))
self.fields['sub_district'].queryset = Sub_district.objects.filter(district_id=district_id).order_by('name')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and fallback to empty City queryset
elif self.instance.pk:
self.fields['sub_district'].queryset = self.instance.district.sub_district_set.order_by('name')
class Remarks_Applicant(ModelForm):
class Meta:
model = Applicant
fields =["status", "roll_no", ]
class Add_Course(ModelForm):
class Meta:
model = Course
fields = '__all__'
class Add_Project(ModelForm):
class Meta:
model = Project
fields = '__all__'
class Add_Session(ModelForm):
class Meta:
model = Session
fields = '__all__'
class Add_Resolution(ModelForm):
class Meta:
model = Resolution
fields = '__all__'
class Add_Financial_aid(ModelForm):
class Meta:
model = Financial_aid
fields = '__all__'
class CreateUserForm(UserCreationForm):
class Meta:
model=User
fields = ['username' , 'email' , 'password1' , 'password2']
widgets = {
'username': forms.NumberInput(attrs={'class': 'form-control input'}),
'email': forms.EmailInput(attrs={'class': 'form-control input'}),
'password1': forms.PasswordInput(attrs={'class': 'form-control input'}),
'password2': forms.PasswordInput(attrs={'class': 'form-control input'}),
}
I have a field in my ModelSerializer which I've set as SerializerMethodField to modify the get behaviour for the field. I could update the data before, now I can't. How can I solve this?
Initially, without using SerializerMethodField, I got data like this:
{
...
"members": [2,3],
...
}
but I added SerializerMethodField to modify the data, then update stopped working.
models.py
# Create your models here.
class Company(models.Model):
members = ArrayField(models.IntegerField(blank=True), blank=True)
...
serializers.py
class AccountSerializer(serializers.ModelSerializer):
user=serializers.StringRelatedField(read_only=False)
class Meta:
model=Account
fields='__all__'
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class CompanySerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=False)
members = serializers.SerializerMethodField()
class Meta:
model = Company
fields = '__all__' #('id', 'name', 'description', 'date_created', 'user', 'status', 'theme', 'members')
def get_members(self, obj):
accounts = Account.objects.filter(id__in=obj.members)
return AccountSerializer(accounts, many=True).data
...
You need to use different serializers for update and create. This serializer works for get only.
Or, you can create a custom field. Django Rest Framework How to update SerializerMethodField
Or, there can be other simpler hooks. If 'create' and 'update' worked as you wanted before modifiying members, then you can do as follow to get everything to default for create and update requests.
Instead of using SerializerMethodField, override serializer representation.
class CompanySerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=False)
class Meta:
model = Company
fields = ('id', 'name', 'description', 'date_created', 'user', 'status', 'theme', 'members', 'members_data')
def to_representation(self, obj)
ret = super().to_representation(obj)
ret["members"] = AccountSerializer(accounts, many=True).data
return ret
Override the __init__ method .
.
class CompanySerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
try:
if self.context['request'].method in ['GET']:
self.fields['members'] = SerializerMethodField()
except KeyError:
pass
class Meta:
model = Company
fields = '__all__' #('id', 'name', 'description', 'date_created', 'user', 'status', 'theme', 'members')
def get_members(self, obj):
accounts = Account.objects.filter(id__in=obj.members)
return AccountSerializer(accounts, many=True).data
...
Or, you can create different field for getting members.
class CompanySerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=False)
members_data = SerializerMethodField()
class Meta:
model = Company
fields = ('id', 'name', 'description', 'date_created', 'user', 'status', 'theme', 'members', 'members_data')
def get_members_data(self, obj):
accounts = Account.objects.filter(id__in=obj.members)
return AccountSerializer(accounts, many=True).data
...
I have the following models:
class Parent(models.Model):
name = models.CharField()
class Child(models.Model):
name = models.CharField()
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
with serializer:
class ChildSerializer(serializers.ModelSerializer):
class Meta:
model = Child
fields = ('id', 'name', 'parent',)
read_only_fields = ('id',)
and ModelViewSet:
class ChildViewSet(viewsets.ModelViewSet):
serializer_class = ChildSerializer
permission_classes = (IsAuthenticated,)
queryset = Child.objects.all()
paginator = None
If I query the api, I get a json structure that looks like:
{
"id": 1,
"name": "Child Name",
"parent": 3
}
Which is exactly what I want. However, if I try to PUT the same data back, I get the error:
ValueError: Cannot assign "3": "Child.parent" must be a "Parent" instance.
How can I make a submission like this work? I should be able to submit my data in the same way I receive it from the API.
You can use PrimaryKeyRelatedField:
Example from DRF Docs:
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Album
fields = ['album_name', 'artist', 'tracks']
Your code would most likely be:
class ChildSerializer(serializers.ModelSerializer):
parent = serializers.PrimaryKeyRelatedField(many=True)
class Meta:
model = Child
fields = ('id', 'name', 'parent',)
read_only_fields = ('id',)
I have a problem where DRF isn't displaying all of my fields correctly for a model class / reference table (specifically the primary key).
My Model Class looks like this (very simple):
class UnitOfIssue(models.Model):
code = models.CharField(max_length=2, primary_key=True)
description = models.CharField(max_length=16)
class Meta:
ordering = ('code',)
def __str__(self):
return "{0} - {1}".format(self.code, self.description)
My Serializer Looks like this:
class UnitOfIssueSerializer(serializers.HyperlinkedModelSerializer):
"""
"""
url = serializers.HyperlinkedIdentityField(
read_only=True,
view_name='unitofissue-detail',
format='html',
lookup_field='code')
class Meta:
model = UnitOfIssue
fields = ('code', 'description', 'url')
# fields = '__all__'
And I'm using a generic view:
class UnitOfIssueDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = UnitOfIssue.objects.all()
serializer_class = UnitOfIssueSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
lookup_field = 'code'
In order for the UnitOfIssue primary key code to be displayed in the auto-generated UI, I have to define fields = ('code', 'description', 'url') in the serializer instead of fields = '__all__'.
I want to just be able to use the '__all__' syntax but I can't figure out what's going wrong.
Also, I'm using Django==1.11.13 and djangorestframework==3.8.2
This issue plagued me for weeks, and yet it was such a simple error. I fixed it by changing the serializer base class from:
class UnitOfIssueSerializer(serializers.HyperlinkedModelSerializer):
to:
class UnitOfIssueSerializer(serializers.ModelSerializer):
I have a problem when I want to override a field in my form
The class looks like below
class UserCreationForm(forms.ModelForm):
class Meta:
model = User
fields = ['password', 'services', 'project', 'email', 'name', 'first_name', 'role']
I want to modify the field 'Services' with another value.
For this I used the get_form function like this :
class UserAdmin(admin.ModelAdmin):
exclude = ('uuid',)
search_fields = ('email', "project")
list_display = ("email", "project", "nb_connexion")
form = UserCreationForm
def get_form(self, request, obj=None, **kwargs):
if obj != None:
print(obj.name)
print(request)
form = super(UserAdmin, self).get_form(request, obj=obj, **kwargs)
form.base_fields['services'].initial = Service.objects.filter(projects=obj.project)
return form
But I still get the same results for all the services while I am only interested in getting the services of one project.Any help would be appreciated.
Thanks
You are currently trying to set initial, which is the initial value selected. If you want to limit the choices, you want to override the queryset instead.
You can alter the form's fields in the __init__ method:
class UserCreationForm(forms.ModelForm):
class Meta:
model = User
fields = ['password', 'services', 'project', 'email', 'name', 'first_name', 'role']
def __init__(self, *args, **kwargs):
super(UserCreationForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.fields['services'].queryset = Service.objects.filter(projects=self.instance.project)
Your UserAdmin class already uses form = UserCreationForm, so all you have to do is remove the get_form method.
class UserAdmin(admin.ModelAdmin):
...
form = UserCreationForm
...