Ignore options which already given in django - django

I created a django forms
class StudentFamilyForm(forms.ModelForm):
class Meta:
model = StudentFamily
fields = '__all__'
exclude = ['created', 'is_deleted']
it is used to create family details for a student. in the StudentFamily model, there is a student one-to-one field.
If i've created a family entry for a student, I don't want to see it in the select input. so how to do that?

Related

How to show a related_name field from Django models connected through a ManyToMany relationship?

New to Django and relational DBs. I'm building the classic Doctor appointment booking app and have come to a point where I don't know what to do. I've created the Doctor model pointing to a Clinic, but in my API the Clinic model won't show a list of all Doctors. How could I achieve this?
class Clinic(models.Model):
name = models.CharField(max_length=200)
class Doctor(models.Model):
clinic = models.ManyToManyField(Clinic, related_name="doctors")
class ClinicSerializer(serializers.ModelSerializer):
class Meta:
model = Clinic
fields = '__all__'
class DoctorSerializer(serializers.ModelSerializer):
class Meta:
model = Doctor
fields = '__all__'
class ClinicViewset(viewsets.ModelViewSet):
queryset = Clinic.objects.all()
serializer_class = ClinicSerializer
class DoctorViewset(viewsets.ModelViewSet):
queryset = Doctor.objects.all()
serializer_class = DoctorSerializer
Django will automatically create the link from Clinic to Doctor. You don't need to (shouldn't) define it. From the docs:
Django also creates API accessors for the “other” side of the relationship – the link from the related model to the model that defines the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all().
The related_name argument that you passed to ManyToManyField when you created the clinic field is the name of the relation from Clinic to Doctor. It is optional and if you didn't pass it, it would be the lower-cased named of the model + _set - doctor_set in your case.
Usually you would set it to a plural in the case of ManyToManyField. In your case: doctors.
Because you have related_name="doctor" currently, you can retrieve a clinic's doctors with: clinic.doctor.all().

Conditionally nest Django serializers

So, I have a foreign key to my User model in many of my models. Now, the serializers for these models are nested, in that they include the entire user object rather than just the id. I have done so as shown bellow:
class BadgeSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = Badge
fields = '__all__'
It works as expected. However, I seldom find myself in a situation where I want just the id. I was wondering what is the best way to conditionally nest my BadgeSerializer...
Now, the best solution I can think of is to have a non-nested BadgeSerializer, which includes only the user id. And then have a NestedBadgeSerializer (extending BadgeSerializer) which does nest the User model and include the entire user object.
class BadgeSerializer(serializers.ModelSerializer):
class Meta:
model = Badge
fields = '__all__'
class NestedBadgeSerializer(BadgeSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = Badge
fields = '__all__'
I am NOT sure if that's the proper way though.

Expected a dictionary, but got str Django Rest Framework

Right now I am creating a user department with a list of users that are a foreign key back to the main user model. I had this working yesterday, but for some reason I screwed it up. I imagine it has something to do with the serializers. I want to be able to post a list of users in this format
['jack', 'tom']
However, even using the raw data api this is not allowing me to do this. Here is my code:
Serializers:
class DepartmentSerializer(serializers.ModelSerializer):
user_department = UserSerializer(many=True)
class Meta:
model = Departments
fields = '__all__'
class DepartmentUpdateSerializer(serializers.ModelSerializer):
user_department = UserSerializer(many=True)
class Meta:
model = Departments
fields = ['department_name', 'department_head', 'user_department']
I swear yesterday it was allowing me to select from a list of users in the api. I could also post and it would work from the front end. However, now whenever I create a department it's expecting a dictionary, which I am not trying to pass.
Dudes, for whatever reason, removing () after the UserSerializer fixed it. If anyone can explain why that would be even better!
class DepartmentSerializer(serializers.ModelSerializer):
user_department = UserSerializer
class Meta:
model = Departments
fields =['department_name', 'department_head', 'user_department']
class DepartmentUpdateSerializer(serializers.ModelSerializer):
user_department = UserSerializer
class Meta:
model = Departments
fields = ['department_name', 'department_head', 'user_department']
When you use the nested serializer you need to add the nested serializer field (user_department in your case) to the fields too, as you can see you used
fields = '__all__'
which does not include your nested serializer field, you need to manually add that to the meta fields

DRF create record with multiple child records in same POST

I am using django-rest-framework 3.3.1 and am struggling to deserialize a new record and related records in the same POST.
My models look like this:
class Employee(models.Model):
name = models.CharField(max_length=128)
locn = models.CharField(max_length=128)
class Degree(models.Model):
employee = models.ForeignKey(Employee, related_name='degrees')
type = models.CharField(max_length=128)
date = models.DateField()
I have a simple serializer for the degree:
class DegreeSerializer(serializers.ModelSerializer):
class Meta:
model = Degree
fields = ('id', 'employee', 'type', 'date',)
and a simple employee serializer:
class EmployeeSerializer(serializers.ModelSerializer):
degrees = DegreeSerializer(many=True)
class Meta:
model = Employee
fields = ('id', 'name', 'locn', 'degrees',)
I want the user to be able to add the new employee and his degrees in the same UI dialog (rather than add the employee first then later add degrees to the now-existing employee). My attempts to put both a new Employee and new Degrees in the same POST fails with DRF telling me that employee is required on the degree items. Is it possible to do this natively in DRF?
A related question is how do you ensure that when the user issues a PUT on the Employee with modified Degree items that those degree items actually replace all of the existing items in the DB?
Thanks.
You need to deal with nested object creation. By default, is not supported, you need to rewrite create() and update() methods from your serializers.
Here, there is an example from DRF docs

Django: One model multi-steps forms

I am trying to build a multi-step forms from one Django model which have 9 fields. The forms are validated in each step and saved after final step into database.
The quick solution I can think of beside Django formWizard is
I have a django model like this:
class Question(models.Model):
name = models.CharField(max_length=100)
Description = models.TextField()
filter = models.CharField(max_length=20)
I split the form into three
class Filter(forms.ModelForm):
class Meta:
model = Question
exclude = ('filter',)
class Name(forms.ModelForm):
class Meta:
model = Question
fields = ('name',)
class Descripton(forms.ModelForm):
class Meta:
model = Question
fields = ('description',)
Write urls and integrate with views for different steps. The question is how can I validate and save multi-steps forms data at last step?
What is your use case for splitting this up into three steps rather than in a single one?
That aside, a simple solution would be to:
Clean/validate the partial data after each submit.
Send the partial data back in hidden fields to your template for the subsequent steps (perhaps Name can inherit or be initialized using Filter, same with Description taking in Name).
Then on the final submit, you'll have all the previous data (some in hidden fields) so you can save it all to your database.