my two model class:
class Bank(models.Model):
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Branch(models.Model):
ifsc = models.CharField(max_length=200)
name = models.CharField(max_length=200)
address = models.TextField(max_length=200)
city = models.CharField(max_length=200)
state = models.CharField(max_length=200)
bank = models.ForeignKey(Bank, on_delete=models.CASCADE,max_length=200)
def __str__(self):
return f"{self.name}"
serializer classes,
class BankSerializer(serializers.ModelSerializer):
class Meta:
model = Bank
fields = '__all__'
class BranchSerializer(serializers.ModelSerializer):
bank = serializers.CharField(source='bank.name', read_only=True)
class Meta:
model = Branch
fields = ["ifsc","name","address","city","state","bank"]
and Views.py
class CityBankNameView(APIView):
def get_object(self, bank_name, city_name):
try:
bank = Bank.objects.get(name=bank_name)
branches = Branch.objects.filter(bank__icontains=bank, city=city_name) #<-- icontains
return branches
except:
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
def get(self,request, bank_name, city_name):
branches = self.get_object(bank_name, city_name)
serializer = BranchSerializer(branches, many=True)
return Response(serializer.data)
I am getting attribute error when using bank__icontains
exact error:
AttributeError at /branches/DELHI/AXIS BANK
Got AttributeError when attempting to get a value for field ifsc on serializer BranchSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the bytes instance.
Original exception text was: 'bytes' object has no attribute 'ifsc'.
I am trying for hours but cannot find any solution to it. I seen various answers but none of them helps solve this one
bank__icontains= expects bank to be a string object, not a Bank object. You can thus rewrite the query to:
branches = Branch.objects.filter(bank=bank, city=city_name)
or if you want the Branches for which the name of the bank contains bank_name, you can filter with:
branches = Branch.objects.filter(bank__name__icontains=bank_name, city=city_name)
Related
I'm trying to validate user input by passing the data to a Serializer class. The said serializer class has no models and inherits from serializers.Serializer.
I'm trying to validate if the input is present in a ModelSerializer class called Country. My code keeps returning the following error: value already exits.
Things I have tried:
field level validation using a method called: validate_country - which works.
I wanted to know if the same could be achieved by calling Country serializer class from inside ValidationSerializer.
models.py
class Country(models.Model):
iso_code = models.CharField(max_length=2, unique=True)
name = models.CharField(max_length=255)
class Meta:
ordering = ("name",)
verbose_name_plural = _("Countries")
def __str__(self):
return self.name
serializers.py
class CountrySerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = ("id", "name", "iso_code")
class ValidationSerializer(serializers.Serializers):
# this serializer does not have a model and only want to validate inputs provided by user
country = ListField(child=CountrySerializer(many=False, required=False), default=list, allow_empty=True)
# sample country input looks like: {"country": ["US", "CA", "GB"]}
# I want to pass the country codes to CountrySerializer to validate if the country codes exists and return a seriliazed object
views.py
class MyView(GenericAPIView):
def get(self):
country=request.query_params['country'].split(",")
ser = ValidationSerializer(data=country)
if not ser.is_valid()
return Response(ser.errors)
else:
#process request
Thank you !
I have the following Models:
class Book(models.Model):
name = models.CharField(max_length=128)
isbn = models.CharField(max_length=13, unique=True)
available = models.BooleanField(default=True)
class Borrow(models.Model):
date = models.DateTimeField(auto_now_add=True)
book = models.ForeignKey(Book)
and the following ModelForm:
class CreateBorrowForm(forms.ModelForm):
class Meta:
model = Borrow
fields = ['book']
def clean_book(self):
book = self.cleaned_data['book']
try:
return Book.objects.get(id=book, available=True)
except Book.DoesNotExist:
raise ValidationError('Book does not exist or it is unavailable')
I would like to have a form that expects the isbn field of the Book model, instead of id. As the isbn field is unique, it does make sense. In the clean_book method I would need to do a little change to have the following line:
return Book.objects.get(isbn=book, available=True)
The problem is that I cannot find an approach to force the form to use a different unique identifier. In my specific case, this is required to avoid brute force enumerating over numerical IDs.
You'd need to use a custom field for that, and override the save() method instead of the clean__field():
class CreateBorrowForm(forms.ModelForm):
book_isbn = forms.CharField()
class Meta:
model = Borrow
fields = ['book_isbn']
def save(self, commit=True):
instance = super().save(commit=False)
book_isbn = self.cleaned_data['book_isbn']
try:
book = Book.objects.get(isbn=book_isbn, available=True)
instance.book = book
except Book.DoesNotExist:
raise ValidationError('Book does not exist or it is unavailable')
if commit:
instance.save()
return instance
I am using DRF to get and create data from and to the API. I was struggling with a model Question and a attribute category which is a model too. So in order to create and read data I had to implement this question's answer method. Therefore, whenever I create a question, its category is an integer but when I read it, is an object.
Whenever I use the default API route I can create and read the data, but I am getting the following error whenever I write a different route:
AttributeError: Got AttributeError when attempting to get a value for field category on serializer QuestionSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the QuerySet instance.
Original exception text was: 'QuerySet' object has no attribute 'category'.
This is my custom code, where something is wrong...:
class UserQuestions(APIView):
permission_classes = [permissions.IsAuthenticated]
def get(self, request, *args, **kwargs):
questions = Question.objects.filter(created_by=request.user.id).all()
data = QuestionSerializer(questions).data
return Response({
'questions': data
})
Just in case, this is my answer's implementation:
class RelatedFieldAlternative(serializers.PrimaryKeyRelatedField):
def __init__(self, **kwargs):
self.serializer = kwargs.pop('serializer', None)
if self.serializer is not None and not issubclass(self.serializer, serializers.Serializer):
raise TypeError('"serializer" no es una clase serializer vĂ¡lida')
super().__init__(**kwargs)
def use_pk_only_optimization(self):
return False if self.serializer else True
def to_representation(self, instance):
if self.serializer:
return self.serializer(instance, context=self.context).data
return super().to_representation(instance)
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class QuestionSerializer(serializers.ModelSerializer):
category = RelatedFieldAlternative(queryset=Category.objects.all(), serializer=CategorySerializer)
answers = AnswerSerializer(many=True, source='answer_set', allow_null=True, required=False)
created_by = UserSerializer(required=False)
def to_representation(self, instance):
response = super().to_representation(instance)
response['category'] = CategorySerializer(instance.category).data
return response
class Meta:
model = Question
fields = '__all__'
And this is the Question model:
class Question(models.Model):
id = models.AutoField(primary_key=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
question = models.CharField(max_length=1000)
...
So, what am I doing wrong?
First of all, you are passing multiple items to serializer so you should use many=True. So in your case, it will be
data = QuestionSerializer(questions, many=True).data
Second, you don't need relatedFieldAlternative. You can just use a nested serailizer.
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class QuestionSerializer(serializers.ModelSerializer):
category = CategorySerializer()
class Meta:
model = Question
fields = '__all__'
i'm trying to work with django-rest-framework and serializers ,and i keep getting this error :
AttributeError: Got AttributeError when attempting to get a value for field
recruitment_date on serializer EmployeeSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the
Project instance.
Original exception text was: 'Project' object has no attribute 'recruitment_date'
models.py :
class Employee(models.Model):
f_name = models.CharField(max_length=50,default='')
l_name = models.CharField(max_length=50,default='')
telephone = models.CharField(max_length=15,default='')
recruitment_date = models.DateField(auto_now_add=False)
salary = models.DecimalField(max_digits=12,decimal_places=2)
def __str__(self):
return self.f_name +' '+self.l_name
class Project(models.Model):
name = models.CharField(max_length=255, default='')
statuts = models.CharField(max_length=10,choices = STATUS,default= STATUS[0])
description = models.TextField(blank=True)
leader = models.OneToOneField(Employee,on_delete=models.CASCADE,related_name = 'leader')
p_employees = models.ManyToManyField(Employee)
estimated_budget = models.DecimalField(max_digits=12,decimal_places=4)
start_date = models.DateField(auto_now_add=False)
end_date = models.DateField(auto_now_add=False)
tasks = models.ManyToManyField(Task)
materials = models.ManyToManyField(Materials)
def __str__(self):
return self.name
serializers.py :
class EmployeeSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Employee
fields=['id','f_name','l_name','telephone','recruitment_date','salary']
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
leader = EmployeeSerializer()
p_employees = EmployeeSerializer(many =True)
tasks = TaskSerializer(many =True)
materials = MaterialsSerializer(many =True)
class Meta :
model = Project
fields = ['name','statuts','description','leader','p_employees',
'start_date','end_date','tasks','materials']
That recruitment_date attribute/column might not actually exist in your Django database. Sure it's in your model, but did you make migrations then migrate?
Try running your development server and see if a message that says "Your models have changed" or something along those lines. Django is pretty good when it comes to those things.
If anything, I highly recommend you just makemigrations and migrate. It won't hurt.
Then
If the database already has that column/attribute, then just do this with your serializer. It's the best "good enough" solution I can do:
class Meta:
model = Employee
fields = '__all__'
I have 2 models that are OneToOne related and model that is FK to 2nd model
models.py
class Legal(TimeStampedModel):
name = models.CharField('Name', max_length=255, blank=True)
class LegalCard(TimeStampedModel):
legal = models.OneToOneField('Legal', related_name='legal_card', on_delete=models.CASCADE)
branch = models.ForeignKey('Branch', related_name='branch', null=True)
post_address = models.CharField('Post address', max_length=255, blank=True)
class Branch(TimeStampedModel):
name = models.CharField('Name',max_length=511)
code = models.CharField('Code', max_length=6)
Using DRF I made them to behave as single model so I can create or update both:
serializer.py
class LegalSerializer(serializers.ModelSerializer):
branch = serializers.IntegerField(source='legal_card.branch', allow_null=True, required=False)
post_address = serializers.CharField(source='legal_card.post_address', allow_blank=True, required=False)
class Meta:
model = Legal
fields = ('id',
'name',
'branch',
'post_address',
)
depth = 2
def create(self, validated_data):
legal_card_data = validated_data.pop('legal_card', None)
legal = super(LegalSerializer, self).create(validated_data)
self.update_or_create_legal_card(legal, legal_card_data)
return legal
def update(self, instance, validated_data):
legal_card_data = validated_data.pop('legal_card', None)
self.update_or_create_legal_card(instance, legal_card_data)
return super(LegalSerializer, self).update(instance, validated_data)
def update_or_create_legal_card(self, legal, legal_card_data):
LegalCard.objects.update_or_create(legal=legal, defaults=legal_card_data)
views.py
class LegalDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Legal.objects.all()
serializer_class = LegalSerializer
I'm trying to save this by sending FK as integer (I just want to post id of the branch), but I receive error
ValueError: Cannot assign "2": "LegalCard.branch" must be a "Branch" instance.
Is there any way to pass over only ID of the branch?
Thank you
In Django, if you only need the FK value, you can use the FK value that is already on the object you've got rather than getting the related object.
Assume you have a Legal and Branch object with id's as 1. Then you can save a LegalCard object by:
LegalCard(legal_id=1,branch_id=1,post_address="Istanbul Street No:1")
Just use legal_card.branch_id instead of legal_card.branch to get just an id, not a related object.
And depth = 1