Django charfield blank=False, but override required=False in admin - django-forms

So I have some charfields that I want to always be required in forms, except for in the admin console. They are also 'list_editable'.
This means the easiest way to do it is to set blank=False on the model, but override required=False just for the admin form.
class MyModel(models.Model):
first_name = models.CharField(max_length=40, null=True)
class MyAdminForm(forms.ModelForm):
first_name = forms.CharField(max_length=40, required=False)
class MyAdmin(admin.ModelAdmin):
list_editable = ('first_name', ...)
form = MyAdminForm
However when a value is set, and you want to set it to null, you can't.
Django won't save it as null in the DB, it will rather try to save it as the empty string "" since it is a charfield.

Related

Serializing custom model fields in TokenObtainPairSerializer

Im using djangorestframework-simplejwt. I want to make TokenObtainPairView take in first_name, last_name, phone_number and email to authenticate instead of the default username and password, so that I can instead make a /register endpoint that will both register and login in a single request. (For reference this is the urlpattern typically used with TokenObtainPairView typically
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
I've been able to make this work with writing normal serializer fields like below
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
first_name = serializers.CharField()
last_name = serializers.CharField()
email = serializers.EmailField()
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
Is there a way to use ModelSerializer to do this instead? e.g something like this (the below doesn't work)
class MyTokenObtainPairSerializer(TokenObtainPairSerializer, ModelSerializer):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']

django rest-framework add fields to ModelSerializer

I have the following serializer:
class AMXModXAdminsSerializer(mixins.GetCSConfigMixin, serializers.ModelSerializer):
admin = serializers.CharField(label='Admin', max_length=35, required=True, write_only=True)
password = serializers.CharField(label='Password', max_length=35, required=False, write_only=True)
access_flags = serializers.MultipleChoiceField(choices=ACCESS_FLAGS_OPTIONS, required=True, write_only=True)
account_flags = serializers.MultipleChoiceField(choices=ACCOUNT_FLAGS_OPTIONS, required=True, write_only=True)
class Meta:
model = CS16Server
fields = ('name', 'amxadmins', 'admin', 'password', 'access_flags', 'account_flags')
read_only_fields = ('name', 'amxadmins',)
When I try to access the url it complains:
Got AttributeError when attempting to get a value for field `admin` on serializer `AMXModXAdminsSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `CS16Server` instance.
Original exception text was: 'CS16Server' object has no attribute 'admin'.
If I add write_only to each field, the error will go away.
The thing is that I have a similar serializer, for the same model, with fields which do not belong to the model and it works perfectly without adding "write_only=True" to each field.
Any idea why one would work and another one no ?
What do u mean "when i access" ? post get put patch ?
Error says:
'CS16Server' object has no attribute 'admin'.
Does it ? if not , where do u intend to write it to ?
If model does not have admin field (as mentioned in error ) you need something like this:
class AMXModXAdminsSerializer(mixins.GetCSConfigMixin, serializers.ModelSerializer):
admin= serializers.SerializerMethodField()
fields ...
...
def get_admin(self, obj):
do somthing with self (contains the request) or the obj you're working on
return theOUTcome
If you set required=False it will not complain anymore because it will not try to get those fields values from db.

Create a serializer for custom user model in django-rest-auth?

I've installed django-rest-framework. Also i've installed django allauth.
Now i want to use django-rest-auth based on previous two, for serializing data
and sending it in json format as answer on my submit form method (for registration/login etc).
I look up into documentation is provided for django-rest-auth
but it feels for me strange, as i inherit(and must do so) from the AbstractBaseUser and not simply do OneToOneField on existing User model.
At the moment the model i assign to the AUTH_USER_MODEL in my settings.py is:
class Account(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, db_index=True, verbose_name='Account Email')
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_employer = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
objects = AccountManager()
USERNAME_FIELD = 'email'
The question is: how can i use serializing in rest-auth the same way, but using my model instead of provided UserProfile model example ?
Yes you may inherit it, and use serializers the way you are saying. It should work. Please state where the error arises when you are using serializers for this.

User has no userprofile when using recommended method

I am adding a field to the user by using the recommend method here. #3 How can I update UserProfile assigned to User model?
When I attempt to save zip code on the /rest-auth/user/ url I get the exception "User has no userprofile."
model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
# custom fields for user
zip_code = models.CharField(max_length=5)
serializer:
class UserSerializer(UserDetailsSerializer):
zip_code = serializers.CharField(source="userprofile.zip_code")
class Meta(UserDetailsSerializer.Meta):
fields = UserDetailsSerializer.Meta.fields + ('zip_code',)
def update(self, instance, validated_data):
profile_data = validated_data.pop('userprofile', {})
zip_code = profile_data.get('zip_code')
instance = super(UserSerializer, self).update(instance, validated_data)
# get and update user profile
profile = instance.userprofile
if profile_data and zip_code:
profile.zip_code = zip_code
profile.save()
return instance
Thank in advance!

Override django form's clean method to change the ModelChoiceField queryset

I have this model:
class PetAttribute(models.Model):
species = models.ForeignKey(PetSpecies, related_name = "pets")
pet_category = models.ForeignKey(PetCategory, related_name = "pets", blank=True, null=True)
pet_type = models.ForeignKey(PetType, related_name = "pets", blank=True, null=True)
additional_fields= models.ManyToManyField( AdditionalField, null= True, blank=True )
Now i want to add an additional option in select (pet_category, pet_type), which is
("0","Other")
in queryset of these. I have tried but form give me an error
Error: Select a valid choice. That choice is not one of the available choices.
here is a one solution of it, but i want to do this by ModelChoiceField
Any suggestion?
Thanks :)
While it is possible, are you sure this is what you want to do? You are telling a field that validates choices to the model objects to accept a non-valid answer.
Creating an "other" PetType and PetCategory object or using empty_label as "other" might make more sense than forcing the ModelChoiceField to accept arbitrary values.
Then to find objects with "other" selected, query for None,
pattrs_w_other_pet_type = PetAttribute.object.filter(pet_type=None)

Resources