How to select related objects with only one query - python-3.x

Models:
class Tag(BaseModel):
tag_name = models.CharField(max_length=250)
slug = models.SlugField()
def save(self, *args, **kwargs):
self.slug = slugify(self.tag_name)
super(Tag, self).save(*args, **kwargs)
def __str__(self):
return str(self.tag_name)
class Tags(BaseModel):
filtertype = models.CharField(max_length=250)
tags = models.ManyToManyField(Tag)
My current solution:
def get(self,request,version):
filtertype = request.query_params.get('filtertype', '')
filtertypes = filtertype.split(",")
tagsList = Tags.objects.filter(filtertype__in=filtertypes).values_list('tags', flat=True).distinct()
queryset = Tag.objects.filter(id__in=tagsList)
context = {"request": request}
serialized = TagListSerializers(queryset, many=True, context=context)
return Response(serialized.data)
Im trying to get all the relevant Tag base on Tags/filtertype. Im wondering how can I do it with only one query.

you can do the query part with this code:
queryset = Tag.objects.filter(tags__filtertype__in=filtertypes)

Related

Django duplicate file to all the records with M2M which is self referencing

I have a Serializer & APIview where i upload a file it should be uploaded to other related records as well.
class Record(models.Model):
name = models.CharField(max_length = 122)
related_records = models.ManyToManyField('self', null = True)
class RecordDocument(models.Model):
record = models.ForeignKey(Record, related_name = 'documents', null = True,
blank= True )
file = models.FileField(max_length=255, blank=True, null=True)
class RecordDocumentSerializer(serializers.ModelSerializer):
save_documents_to_related_records = serializers.BooleanField()
class Meta:
model = RecordDocument
fields = ( 'save_documents_to_related_records', 'file',
'record' )
class RecordDocumentUploadView(APIView):
def post(self, request, *args, **kwargs):
'how do i get serializers field **save_documents_to_related_records** and save
the file on **related_records** which is not used in serializer till now if
there are any inside it'
You can try this.
class RecordDocumentUploadView(APIView):
def post(self, request, *args, **kwargs):
serializer = RecordDocumentSerializer(data = request.data)
if serializer.is_valid():
input_data = serializer.validated_data
flag = input_data.pop('save_documents_to_related_records')
new_document = RecordDocument.objects.create(**input_data)
if flag:
...
else:
return Response(status = status.HTTP_400_BAD_REQUEST)

How to capture a field instance during django-import-export upload

I'd like to import data into my resource minus the school field because the logged in user already belongs to a specific school. How would I do it without having the school field in my excel???
class uploadStudents(LoginRequiredMixin,View):
context = {}
def get(self,request):
form = UploadStudentsForm()
self.context['form'] = form
return render(request,'upload.html',self.context)
def post(self, request):
form = UploadStudentsForm(request.POST , request.FILES)
data_set = Dataset()
if form.is_valid():
file = request.FILES['file']
extension = file.name.split(".")[-1].lower()
resource = ImportStudentsResource()
if extension == 'csv':
data = data_set.load(file.read().decode('utf-8'), format=extension)
else:
data = data_set.load(file.read(), format=extension)
result = resource.import_data(data_set, dry_run=True, collect_failed_rows=True, raise_errors=True)
if result.has_validation_errors() or result.has_errors():
messages.success(request,f'Errors experienced during import.')
print("error", result.invalid_rows)
self.context['result'] = result
return redirect('import_students')
else:
result = resource.import_data(data_set, dry_run=False, raise_errors=False)
self.context['result'] = None
messages.success(request,f'Students uploaded successfully.')
else:
self.context['form'] = UploadStudentsForm()
return render(request, 'upload.html', self.context)
The resource
class ImportStudentsResource(resources.ModelResource):
school = fields.Field(attribute = 'school',column_name='school', widget=ForeignKeyWidget(School, 'name'))
klass = fields.Field(attribute = 'klass',column_name='class', widget=ForeignKeyWidget(Klass, 'name'))
stream = fields.Field(attribute = 'stream',column_name='stream', widget=ForeignKeyWidget(Stream, 'name'))
class Meta:
model = Student
fields = ('school','student_id','name','year','klass','stream')
import_id_fields = ('student_id',)
import_order = ('school','student_id','name','year','klass','stream')
Either remove 'school' from your 'fields' declaration, or add it to the 'exclude' list.
docs
Edit
To include a school_id which is associated with the logged in user, you'll need to create the Resource with this school_id:
Resource
class ImportStudentsResource(resources.ModelResource):
def __init__(self, school_id):
super().__init__()
self.school_id = school_id
def before_save_instance(self, instance, using_transactions, dry_run):
instance.school_id = self.school_id
post()
def post(self, request):
# skipped existing code
school_id = get_school_id_from_logged_in_user(self.request)
resource = ImportStudentsResource(school_id)

How do I get a serializer with an instance as a Foreign key?

How do I get a serializer with an instance as a Foreign key? Here is my model and serializer:
class ChargeSchedule(models.Model):
vehicle = models.OneToOneField(Vehicle, on_delete=models.PROTECT, related_name='vehicle_charge_schedule')
max = models.FloatField()
min = models.FloatField()
class ChargeScheduleSerializer(serializers.ModelSerializer):
class Meta:
model = ChargeSchedule
fields = '__all__'
When I try to validate the serializer I get an error saying 'This field must be unique':
class ChargeScheduleViewSet(ModelViewSet):
model = ChargeSchedule
serializer_class = ChargeScheduleSerializer
def create(self, request, *args, **kwargs):
# request.data = {'min': 10, 'max': 100}
vehicle = request.user.vehicle
request.data['vehicle'] = vehicle.id
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) # FAILS HERE, {ValidationError}{'vehicle': [ErrorDetail(string='This field must be unique.', code='unique')]}
How can I validate this serializer using the Vehicle instance?
Try this:
def create(self, request, *args, **kwargs):
# request.data = {'min': 10, 'max': 100}
vehicle = request.user.vehicle
ser_data = request.data
ser_data['vehicle'] = vehicle.id
serializer = self.get_serializer(data=ser_data)
serializer.is_valid(raise_exception=True)

Image upload crud operations in django-restframework

Im new to django, i want to create API for image upload CRUD in drf.
i have done create and read images , it works but dont know how to update and delete it by using id
models.py
class File(models.Model):
file = models.FileField(blank=False, null=False)
def __str__(self):
return self.file.name
serializers.py
class FileSerializer(serializers.ModelSerializer):
class Meta:
model = File
fields = "__all__"
views.py
class FileUploadView(ListAPIView):
parser_class = (FileUploadParser,)
serializer_class = FileSerializer
def get_queryset(self):
queryset = File.objects.all()
return queryset
def post(self, request, *args, **kwargs):
print(request.data)
file_serializer = FileSerializer(data=request.data)
print(file_serializer)
if file_serializer.is_valid():
file_serializer.save()
return Response(
file_serializer.data,
status=status.HTTP_201_CREATED
)
else:
return Response(
file_serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
i want to know how update and delete works
Thank you #manpikin, by doing this way, we can solve it easly
class FileViewSet(viewsets.ModelViewSet):
queryset = File.objects.all()
serializer_class = FileSerializer
but in my case there is some hidden code in between so i have done it in this way, i hope this will help some one facing same problem like me
views.py
class FileUploadView(ListAPIView):
parser_class = (FileUploadParser,)
serializer_class = FileSerializer
def get_queryset(self):
queryset = File.objects.all()
return queryset
def post(self, request, *args, **kwargs):
print(request.data)
file_serializer = FileSerializer(data=request.data)
print(file_serializer)
if file_serializer.is_valid():
file_serializer.save()
return Response(
file_serializer.data,
status=status.HTTP_201_CREATED
)
else:
return Response(
file_serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
def put(self, request):
imageid = self.request.POST.get('id')
f_obj = File.objects.filter(id=imageid) #File is my model name
file_serializer = FileSerializer(f_obj, data=request.data)
print(file_serializer)
if file_serializer.is_valid():
file_serializer.save()
return Response(
file_serializer.data,
status=status.HTTP_201_CREATED
)
else:
return Response(
file_serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
def delete(self, request):
imageid = self.request.POST.get('id')
f_obj = File.objects.filter(id=imageid) #File is my model name
if f_obj.exists():
f_obj.delete()
return Response(
{
"Status": True,
"Message": "image deleted"
}
)
update and delete will work in this way

Cannot submit the form with foreign key in Django

I can't submit the form with foreign key. Is it anything with foreign key?
I always redirect to the destination_list since the form is not saving.
No error is showing.
models.py
class Region(models.Model):
region = models.CharField("Region",max_length=45,blank=True)
status = models.CharField("Status",max_length=45,blank=True)
selected_region = models.CharField("Selected Region",max_length=45,blank=True)
def __str__(self):
return self.region
def get_absolute_url(self):
return reverse('update2', args=[str(self.id)])
def get_delete_url(self):
return reverse('delete2', args=[str(self.id)])
class Destination(models.Model):
region1 = models.ForeignKey(Region)
destination = models.CharField("destination",max_length=30,blank=False,unique=True)
status = models.CharField("status",max_length=30,blank=False,unique=True)
selected_destination = models.CharField("select destination",max_length=30)
def __str__(self):
return self.destination
forms.py
class DestinationForm(forms.ModelForm):
class Meta:
model = Destination
fields = [ 'region1','destination','status','selected_destination']
def __init__(self, *args, **kwargs):
super(DestinationForm, self).__init__(*args, **kwargs)
for key in self.fields:
self.fields[key].widget.attrs['class'] = 'form-control'
views.py
(I have redirect to destination_list if form is not submitted)
def add_destination(request):
form = DestinationForm()
context = {
"form": form
}
if request.method == 'POST':
form = DestinationForm(request.POST)
if form.is_valid():
form.save()
else:
return redirect(destination_list)
return render(request,'adddestination.html',context)

Resources