missing fields of base class django serializer - django

I have few classes:
class Correspondent(models.Model):
title = models.CharField(max_length=60)
class Subject(models.Model):
title = models.CharField(max_length=60)
class Letter(models.Model):
correspondent = models.ForeignKey(Correspondent,
on_delete=models.SET_NULL, null=True)
subject = models.ForeignKey(Subject, on_delete=models.SET_NULL, null=True)
description = models.TextField(max_length=600, blank=True)
case_number = models.CharField(max_length=100, blank=True)
inventory_number = models.CharField(max_length=100, blank=True)
note = models.TextField(max_length=300, blank=True)
user = models.ForeignKey(User, editable=False, on_delete=models.SET_NULL, null=True)
date = models.DateField(default=datetime.date.today)
date_creation = models.DateTimeField(auto_now_add=True)
class IncomingLetter(Letter):
response_to = models.ForeignKey('OutgoingLetter', on_delete=models.SET_NULL, null=True, blank=True)
outgoing_number = models.CharField(max_length=120, blank=True)
incoming_number = models.CharField(max_length=120, blank=True)
class OutgoingLetter(Letter):
response_to = models.ForeignKey(IncomingLetter, on_delete=models.SET_NULL, null=True, blank=True)
outgoing_number = models.CharField(max_length=120, blank=True)
and in a view i trying to send json with serialized class B instances:
from django.http import JsonResponse
from django.core import serializers
from .models import IncomingLetter
def index(request):
....
some_data = IncomingLetter.objects.all()
serialized_data = serializers.serialize('json', some_data)
return JsonResponse(json.dumps(serialized_data), safe=False)
and response missed all Letter fields in json. Is there a way to not serialize it manually?
serialized_data == {"model": "letters.incomingletter", "pk": 4, "fields": {"response_to": 3, "outgoing_number": "12312321", "incoming_number": "123123"}}
SOLVED # (not sure)
I wrote simple serializer, but not sure is this cleanest way(many unnecessary fields, but it easy to clean):
class LetterSerializer:
def __init__(self):
self.serialized_data = {}
def serialize(self, data):
for idx, instance in enumerate(data):
serialized_instance_data = {}
for key, value in instance.__dict__.items():
serialized_instance_data[key] = str(value)
self.serialized_data[idx] = serialized_instance_data
return self.serialized_data

Related

Can I remove a set of ManyToMany objects using SafeDeleteModel?

Soft_delete_cascade was applied to the entire model using the django-safedelete library.
However, if you remove the corresponding many to many object as in the code below, it is not deleted from the set of objects.
What should I do?
# models.py
from django.db import models
from safedelete import SOFT_DELETE_CASCADE, HARD_DELETE
from safedelete.models import SafeDeleteModel
class Post(SafeDeleteModel):
_safedelete_policy: int = SOFT_DELETE_CASCADE
category = models.CharField("카테고리", max_length=100, null=True, blank=True)
title = models.CharField("제목", max_length=300, null=True, blank=True)
created_at = models.DateTimeField("생성일시", auto_now_add=True)
updated_at = models.DateTimeField("수정시간", auto_now=True)
tags = models.ManyToManyField("Tag", through="TagPostAssociation", related_name="posts")
def __str__(self):
return f"글(ID:{self.id}/제목:{self.title})"
class Tag(SafeDeleteModel):
_safedelete_policy: int = SOFT_DELETE_CASCADE
value = models.CharField("태그 값", max_length=100)
created_at = models.DateTimeField("생성일시", auto_now_add=True)
updated_at = models.DateTimeField("수정시간", auto_now=True)
class Meta:
verbose_name = verbose_name_plural = "태그"
def __str__(self):
return f"태그(ID:{self.id}/값:{self.value})"
class TagPostAssociation(SafeDeleteModel):
_safedelete_policy: int = HARD_DELETE
tag = models.ForeignKey(to=Tag, verbose_name="태그", on_delete=models.CASCADE)
post = models.ForeignKey(to=Post, verbose_name="글", on_delete=models.CASCADE)
created_at = models.DateTimeField("생성일시", auto_now_add=True)
updated_at = models.DateTimeField("수정시간", auto_now=True)
class Meta:
verbose_name = verbose_name_plural = "글-태그"
def __str__(self):
return f"글{self.post.id})-태그({self.tag.id})"
>>> post = Post.objects.get(id=2)
>>> tag = Tag.objects.get(id=2)
>>> post.tags.all()
<SafeDeleteQueryset [<Tag: 태그(ID:2/값:hair)>, <Tag: 태그(ID:1/값:test)>]>
>>> post.tags.remove(tag)
>>> post.tags.all()
<SafeDeleteQueryset [<Tag: 태그(ID:2/값:hair)>, <Tag: 태그(ID:1/값:test)>]>
I tried to delete the many to many object using the m2m_changed signal, but it didn't work.

django - How can I prefill formset forms data using database query result?

I am creating a student attendance form where need to get details of student name, student class and Id from student model based on teacher selecting student class in one form. I have tried using initial by using for loop on query data to prefill the form in formset, however it populates data for one record only. Below is the code for forms.py, models and views.py. Can someone help on this
forms.py
class student(models.Model):
studentid = models.AutoField(primary_key=True)
Gender = models.CharField(max_length=6, choices=gender, null=True)
Name = models.CharField(max_length=100, null=True)
DOB = models.DateField(null=True)
Image = models.ImageField(null=True, upload_to='images')
Status = models.CharField(max_length=10, choices=statchoice, null=True)
Father_name = models.CharField(max_length=100, null=True)
Mother_name = models.CharField(max_length=100, null=True)
Address = models.CharField(max_length=200, null=True)
Contact_no = models.IntegerField(null=True)
Email = models.EmailField(null=True)
Admission_class = models.CharField(max_length=40, null=True, choices=grade)
Admission_date = models.DateField(null=True)
Current_class = models.CharField(max_length=40, null=True, choices=grade)
Leaving_date = models.DateField(null=True, blank=True)
objects = models.Manager()
def __str__(self):
return str(self.studentid)
class student_attendance(models.Model):
Student_ID = models.CharField(max_length=100, null=True)
Student_Name = models.CharField(max_length=100, null=True)
Student_class = models.CharField(max_length=100, null=True, choices=grade)
Attendance_date = models.DateField(null=True, auto_now_add=True, blank=True)
Attendance_status = models.CharField(choices=attendance, null=True, max_length=10)
objects = models.Manager()
Views.py
def student_attend(request):
if request.method == 'POST':
data = request.POST.get('studentGrade')
formset_data = student.objects.filter(Current_class=data)
AttendanceFormSet = formset_factory(std_attendance, extra=(len(formset_data))-1)
for element in formset_data:
formset = AttendanceFormSet(initial=[
{'Student_ID': element.studentid, 'Student_Name':element.Name, 'Student_class':element.Current_class, 'Attendance_status':"Present"}
])
param = {'formset':formset}
return render(request, 'home/student_attendance.html', param)
return render(request, 'home/student_attendance.html')
form.py:
class student_register(ModelForm):
class Meta:
model = student
fields = '__all__'
class std_attendance(ModelForm):
class Meta:
model = student_attendance
fields = '__all__'
Each iteration in your loop you override the formset, that is why only a single form is filled, you need to fill the param with all the forms inside the loop this way:
initial = []
for element in formset_data:
initial.append({'Student_ID': element.studentid, 'Student_Name':element.Name, 'Student_class':element.Current_class, 'Attendance_status':"Present"}
formset = AttendanceFormSet(initial=initial)

Query django foreignkey relationship

I am developing an audit management information system where I can record all finding related to an audit. I have models with foreignkeys relationship. How do I see all findings with a particular assignment and audit_title and unit?
See relevant codes below.
model.py content
class Unit(models.Model):
unit_name = models.CharField(max_length=30, blank=True, null=True)
def __unicode__(self):
return self.unit_name
class Assignment(models.Model):
assignment_name = models.CharField(max_length=30, blank=True, null=True)
def __unicode__(self):
return self.assignment_name
class Task(models.Model):
task_title = models.CharField(max_length=35, blank=True, null=True)
return self.task_title
class Finding(models.Model):
assignment = models.ForeignKey(Assignment, blank=True, null=True)
audit_title = models.ForeignKey(Task, blank=True, null=True)
auditor = models.ManyToManyField(User, blank=True)
unit = models.ForeignKey(Unit, blank=True, null=True)
audit_period = models.DateField(auto_now_add=False, auto_now=False, blank=True, null=True)
contact_person = models.CharField('Contact Person', max_length=500, blank=True, null=True)
finding = models.TextField('Detail Finding', max_length=500, blank=True, null=True)
be = models.CharField(max_length=30, blank=True, null=True)
form.py
class FindingSearchForm(forms.ModelForm):
class Meta:
model = Finding
fields = ['assignment',
'audit_title',
'unit',
'be',
]
Am I have the following in my views.py but I have this error invalid literal for int() with base 10: ''
views.py content
def finding_list(request):
title = 'List of Finding'
queryset = Finding.objects.all()
queryset_count = queryset.count()
form = FindingSearchForm(request.POST or None)
context = {
"title": title,
"form": form,
"queryset_count": queryset_count,
}
if request.method == 'POST':
unit = form['unit'].value()
audit_title = form['audit_title'].value()
assignment = form['assignment'].value()
queryset = Finding.objects.all().order_by('-timestamp').filter(be__icontains=form['be'].value(),
unit_id=unit,
assignment_id=assignment,
audit_title_id=audit_title,)
if request.method == 'POST':
unit = form['unit'].value()
audit_title = form['audit_title'].value()
assignment = form['assignment'].value()
queryset = Finding.objects.all().order_by('-timestamp').filter(be__icontains=form['be'].value()
)
if (unit != ''):
queryset = queryset.filter(unit_id=unit)
if (audit_title != ''):
queryset = queryset.filter(audit_title_id=audit_title)
if (assignment != ''):
queryset = queryset.filter(assignment_id=assignment)

DRF post request multiple inner serializers

i have three models named Smoker,Switch,Survey i have smoker as foreign key in Switch model and switch as foreign key in Survey model
class Smoker(models.Model):
first_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=50, blank=True, null=True)
mobile = models.IntegerField(null=True, blank=True)
gender = models.BooleanField(blank=True, null=True)
age = models.ForeignKey(Age,models.DO_NOTHING,blank=True, null=True)
occupation = models.ForeignKey(Occupation, models.DO_NOTHING, blank=True, null=True)
class Switch(models.Model):
time = models.TimeField(blank=True, null=True)
count_outers = models.IntegerField(blank=True, null=True)
count_packs = models.IntegerField(blank=True, null=True)
smoker = models.ForeignKey(Smoker, models.DO_NOTHING, blank=True, null=True)
new_brand = models.ForeignKey(NewBrand, models.DO_NOTHING, blank=True, null=True)
new_sku = models.ForeignKey(NewSku, models.DO_NOTHING, blank=True, null=True)
# def __str__(self):
# return self.time.strftime("%H:%M")
class Survey(models.Model):
user = models.ForeignKey(User, models.DO_NOTHING, blank=True, null=True)
date = models.DateField(null=True, blank=True)
bool_switch = models.BooleanField(null=True, blank=True)
reason = models.ForeignKey(Reason, models.DO_NOTHING, null=True, blank=True)
shift = models.ForeignKey(ShiftingTime, models.DO_NOTHING, null=True, blank=True)
current_brand = models.ForeignKey(CurrentBrand, models.DO_NOTHING, null=True, blank=True)
current_sku = models.ForeignKey(CurrentSku, models.DO_NOTHING, null=True, blank=True)
pos = models.ForeignKey(Pos, models.DO_NOTHING, null=True, blank=True)
switch = models.ForeignKey(Switch, models.DO_NOTHING, null=True, blank=True)
and here i have my serializers:
class SmokerSerializer(serializers.ModelSerializer):
class Meta:
model = Smoker
fields = '__all__'
class SwitchSerializer(serializers.ModelSerializer):
smoker = SmokerSerializer()
class Meta:
model = Switch
fields = '__all__'
def create(self, validated_data):
smoker_data = validated_data.pop('smoker', None)
if smoker_data:
smoker = Smoker.objects.create(**smoker_data)
validated_data['smoker'] = smoker
return Switch.objects.create(**validated_data)
class SurveySerializer(serializers.ModelSerializer):
switch = SwitchSerializer()
class Meta:
model = Survey
fields = '__all__'
def create(self, validated_data):
switch_data = validated_data.pop('switch', None)
if switch_data:
switch = Switch.objects.create(**switch_data)
validated_data['switch'] = switch
return Survey.objects.create(**validated_data)
and i make a generic for for Creating and listing all the survey
class SurveyCreateAPIView(generics.ListCreateAPIView):
def get_queryset(self):
return Survey.objects.all()
serializer_class = SurveySerializer
for each displayed survey i have to display switch data related to it and inside the switch object i need to display the smoker object inside it so each survey object must look like this
{
"id": 11,
"switch": {
"id": 12,
"smoker": {
"firstname":"sami",
"lastname:"hamad",
"mobile":"7983832",
"gender":"0",
"age":"2",
"occupation":"2"
},
"time": null,
"count_outers": 5,
"count_packs": 7,
"new_brand": 2,
"new_sku": 2
},
"date": "2018-12-08",
"bool_switch": true,
"user": 7,
"reason": 3,
"shift": 2,
"current_brand": 6,
"current_sku": 4,
"pos": 2
},
but when i make a POST request it is giving me this error
ValueError at /api/v2/surveysync/ Cannot assign
"OrderedDict([('first_name', 'aline'), ('last_name', 'youssef'),
('mobile', 7488483), ('gender', False), ('age', ),
('occupation', )])": "Switch.smoker" must be
a "Smoker" instance.
so please help and thank you so much!
You're going along the right path but you're saving the switch objects manually instead of allowing the SwitchSerializer do it for you. Same thing with create method in switch serializer. It should be this way:
class SmokerSerializer(serializers.ModelSerializer):
class Meta:
model = Smoker
fields = '__all__'
class SwitchSerializer(serializers.ModelSerializer):
smoker = SmokerSerializer()
class Meta:
model = Switch
fields = '__all__'
def create(self, validated_data):
smoker_data = validated_data.pop('smoker', None)
if smoker_data:
serializer = SmokerSerializer(data=smoker_data, context=self.context)
if serializer.is_valid():
validated_data['smoker'] = serializer.save()
return super().create(validated_data)
class SurveySerializer(serializers.ModelSerializer):
switch = SwitchSerializer()
class Meta:
model = Survey
fields = '__all__'
def create(self, validated_data):
switch_data = validated_data.pop('switch', None)
if switch_data:
serializer = SwitchSerializer(data=switch_data, context=self.context)
if serializer.is_valid():
validated_data['switch'] = serializer.save()
return super().create(validated_data)
In SwitchSerializer you defined the create function as a method of the inner Meta class and not as a member of SwitchSerializer class. Try this
class SwitchSerializer(serializers.ModelSerializer):
smoker = SmokerSerializer()
class Meta:
model = Switch
fields = '__all__'
def create(self, validated_data):
smoker_data = validated_data.pop('smoker', None)
if smoker_data:
smoker = Smoker.objects.create(**smoker_data)
validated_data['smoker'] = smoker
return Switch.objects.create(**validated_data)

How to serialize list of strings with Django Rest Framework

I have serializer in Django rest framework as follows:
class StateSerializer(serializers.ModelSerializer):
kilometers = Field(source='mileage')
pictures = StatePictureSerializer(many=True, read_only=True)
class Meta:
model = Inspection # Options
fields = ('kilometers', 'inspection_date', 'pictures')
And StatePictureSerializer is as follows:
class StatePictureSerializer(serializers.ModelSerializer):
blob_url = Field(source='public_url')
class Meta:
model = Inspection_Picture
fields = ('blob_url', )
As result I get something as follows:
{
"kilometers": 64431,
"inspection_date": null,
"pictures": [
{"blob_url": "path/to/photo"},
{"blob_url": "path/to/photo"},
{"blob_url": "path/to/photo"},
{"blob_url": "path/to/photo"},
{"blob_url": "path/to/photo"}
]
}
Thus, pictures is an array of objects.
What I want is an array of strings, for example:
"pictures": ["path/to/photo", "path/to/photo", "path/to/photo", "path/to/photo", "path/to/photo"]
Any idea how to do that?
EDIT
Inspection model is as follows:
class Inspection(models.Model):
customerReference = models.CharField(max_length=50, blank=True, null=True)
extraReference = models.CharField(max_length=50, blank=True, null=True)
itemReference = models.IntegerField(blank=True, null=True)
vehicle = models.ForeignKey(to=Vehicle)
mileage = models.IntegerField()
timeStamp = models.DateTimeField(auto_now_add=True)
inspection_date = models.DateTimeField(null=True)
features = models.ManyToManyField(to=Feature)
pictures = models.ManyToManyField(to=Images, through="Inspection_Picture")
damages = models.ManyToManyField(to=Damage)
parts = models.ManyToManyField(to=Part)
checks = models.ManyToManyField(to=CheckType, through=Inspection_Check)
featuresFlat = models.ManyToManyField(to=FeatureFlat, through=Inspection_FeatureFlat)
And Images model is as follows:
class Images(models.Model):
"""Model for storing uploaded photos"""
filename = models.CharField(max_length=255)
extension = models.CharField(max_length=40)
key_data = models.CharField(max_length=90, unique=True, blank=True, null=True)
upload_date = models.DateTimeField(auto_now_add=True)
upload_identification = models.CharField(max_length=50, blank=True, null=True)
url = models.CharField(max_length=1024, blank=True, null=True)
stored = models.BooleanField(default=False)
thumbnailed = models.BooleanField(default=False)
thumbnailed_treated = models.BooleanField(default=False)
protected = models.BooleanField(default=False)
source = models.CharField(max_length=50, blank=True, null=True)
#property
def key_generate(self):
"""returns a string based unique key with length 80 chars"""
while 1:
key = str(random.getrandbits(256))
try:
Images.objects.get(key=key)
except:
return key
def __unicode__(self):
return self.upload_identification
def public_url(self):
return settings.AZURE_URL_FULL + self.url
I think in your case SerializerMethodField would be a right choice as follows. There may be <field_name> mismatch in the code below. Please make it working according your model. I assume the field names based on your serializer above.
class StateSerializer(serializers.ModelSerializer):
kilometers = Field(source='mileage')
pictures = serializers.SerializerMethodField('get_pictures')
class Meta:
model = Inspection # Options
fields = ('kilometers', 'inspection_date', 'pictures')
def get_pictures(self, obj):
return [each.public_url() for each in obj.pictures.all() ]