Django multipart/form-data pass Dict & File - python

I want to create a post requests that sends a file along with information in the form of a dictionary. I have the following implementation:
# conftest.py
import pytest
#pytest.fixture
def api_client():
from rest_framework.test import APIClient
return APIClient()
Testing with pytest:
# test_dataset.py
#pytest.mark.django_db()
class TestDatasetEndpoint:
def test_dataset_create(self, api_client):
data_raw = baker.make(Dataset)
serialized_dataset = DatasetSerializer(data_raw).data
print(serialized_dataset)
file_path = "./Top 250s in IMDB.csv"
with open(file_path, "rb") as fp:
encoded_data = encode_multipart(
BOUNDARY, {"data": serialized_dataset, "file": fp}
)
response_post = api_client.post(
reverse("datasets-list"),
encoded_data,
content_type="multipart/form-data; boundary=BOUNDARY",
)
assert response_post.status_code == 201
Server side:
# views.py
class DatasetViewSet(viewsets.ModelViewSet):
queryset = Dataset.objects.all()
serializer_class = DatasetSerializer
def create(self, request, *args, **kwargs) -> Response:
data = request.data
return Response(request.data["data"], status=status.HTTP_201_CREATED)
Lastly, the Dataset model is:
class Dataset(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100)
path = models.CharField(max_length=100, editable=False, null=True, blank=True)
description = models.CharField(max_length=500, null=True, blank=True)
useCase = models.CharField(max_length=100, editable=False, null=True, blank=True)
useCaseSpecificVariable = models.CharField(
max_length=50, editable=False, null=True, blank=True
)
origin = models.CharField(max_length=50, editable=False, default="")
creationDate = models.DateTimeField(editable=False, null=True, blank=True)
workflowsUsedOn = models.JSONField(blank=True, null=True)
owners = models.JSONField(blank=True, null=True)
sampleSize = models.IntegerField(editable=False, default=0)
featureSize = models.IntegerField(editable=False, default=0)
metadataPath = models.CharField(
max_length=100, editable=False, null=True, blank=True
)
timeFrom = models.DateTimeField(editable=False, null=True, blank=True)
timeUntil = models.DateTimeField(editable=False, null=True, blank=True)
The response i am getting is a combination of the dict and the file data. How can i handle the data and the file in the server side (views.py)?

Django can handle such requests via form. So the pattern is the following:
forms.py
from django import forms
class DatasetForm(forms.Form):
class Meta:
model = Dataset
views.py
class DatasetViewSet(viewsets.ModelViewSet):
queryset = Dataset.objects.all()
serializer_class = DatasetSerializer
def create(self, request, *args, **kwargs) -> Response:
dataset_form = DatasetForm(request.POST, request.FILES)
if dataset_form.is_valid():
dataset = dataset_form.save()
return Response(self.serializer_class(dataset).data, status=status.HTTP_201_CREATED)
else:
return Response(dataset_form.error_messages, status=status.HTTP_400_BAD_REQUEST)
Note that you will need to have a field that can store file on your model. E.g: file = models.FileField(upload_to='attachments', blank=False)
Then content of fields in dictionary (and content of your file) will be automatically mapped via form to the relevant fields.
See additional info: https://docs.djangoproject.com/en/4.0/topics/forms/

Related

django rest frame work: model fields on Django Rest Frame write error

I have a django app with following sections
models:
class Report(models.Model):
created_by_user=models.ForeignKey(User,on_delete=models.CASCADE)
planet_name = models.CharField(max_length=100)
outage_id = models.IntegerField(blank=True, default=0)
unit_name = models.CharField(max_length=10, blank=True, null=True)
responsible_group = models.CharField(max_length=50, blank=True)
alarm_num = models.IntegerField(blank=True, default=0)
raised_alarm = models.CharField(max_length=255, blank=True)
start_time = models.DateTimeField(blank=True)
end_time = models.DateTimeField(blank=True)
event_desc = models.TextField(max_length=5000, blank=True)
power_changes = models.FloatField(blank=True)
rel_asset = models.CharField(max_length=255, blank=True)
event_cause = models.TextField(max_length=1000, blank=True)
maintenance_action = models.TextField(max_length=1000, blank=True)
maintenance_cost = models.IntegerField(blank=True)
maintenance_mh = models.IntegerField(blank=True)
maintenance_dc = models.TextField(max_length=5000, blank=True)
serializer:
class ReportSerializer(serializers.ModelSerializer):
created_by_user = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model=Report
fields='__all__'
view:
class ReportCreateView(APIView):
def post(self,request, *args, **kwargs):
received_data=ReportSerializer(data=request.data, context = {"request": request})
if received_data.is_valid():
received_data.save()
return Response(received_data.data, status=status.HTTP_201_CREATED)
return Response(received_data.errors,status.HTTP_400_BAD_REQUEST)
but when I send a report by Post method this error rise:
(1048, "Column 'start_time' cannot be null")
How I can fix it?I set blank=True for all fields but why it raise errors?

Perform update query after delete in django cbv

I'm trying to update other table after successful delete of of data. Below is my
views.py
class AttendeeDeleteView(DeleteView):
model = Attendee
success_url = reverse_lazy('index')
def get_form_kwargs(self):
id = self.kwargs['id'] # get value of enr
Payment.objects.filter(pk=id).update(registered=0)
In my urls.py
url(r'^delete/(?P<pk>\d+)$', AttendeeDeleteView.as_view(template_name="includes/attendee_delete.html"), name='attendee_delete',),
My Current code successfully delete the item but failed to update the other table.
my model
class Payment(models.Model):
id = models.AutoField(primary_key=True)
payee = models.CharField(max_length=200, blank=True, null=True)
contact = models.CharField(max_length=200,blank=True, null=True)
batch = models.CharField(max_length=200, null=True, blank=True)
ticketNumber = models.CharField(max_length=200)
ticketType = models.CharField(max_length=200, choices=TICKET_CHOICES, default='paid')
date = models.DateField('Date Paid (MM/DD/YYYY)', max_length=200, null=True, blank=True)
remarks = models.CharField(max_length=200 ,blank=True, null=True)
registered = models.BooleanField(default=False)
def __str__(self):
return self.payee
class Attendee(models.Model):
id = models.AutoField(primary_key=True)
payment = models.OneToOneField(Payment, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200)
batch = models.CharField(max_length=200, blank=True, null=True)
department = models.CharField(max_length=200, choices=DEPT_CHOICES, default='')
remarks = models.CharField(max_length=200, blank=True, null=True)
UPDATE 1:
I followed this came up with
def get(self, request, *args, **kwargs):
id = kwargs['pk'] # get value of enr
context = Payment.objects.filter(pk=id).update(registered=0)
return self.render_to_response(context)
but it returned context must be a dict rather than int.
I think def get_form_kwargs(self): doesn't executed, because it used for FormMixin. But, you can also handle it inside get() function.
def get(self, request, *args, **kwargs):
attendee = self.get_object()
Payment.objects.filter(pk=attendee.payment.pk).update(registered=0)
context = self.get_context_data(object=attendee)
return self.render_to_response(context)
See this https://ccbv.co.uk/projects/Django/1.11/django.views.generic.edit/DeleteView/ for more..
Edit:
This solution below if still getting a problem when using get() method.
from django.http import HttpResponseRedirect
....
def delete(self, request, *args, **kwargs):
"""
Calls the delete() method on the fetched object and then
redirects to the success URL.
"""
self.object = self.get_object()
success_url = self.get_success_url()
Payment.objects.filter(pk=self.object.payment.pk).update(registered=0)
self.object.delete()
return HttpResponseRedirect(success_url)

How to create a Event in Django-Scheduler while creating a Object in Django?

I am a total newbie in Python and new on StackOverFlow. If I am missing something please let me know
This is Django-scheduler App:- https://github.com/llazzaro/django-scheduler
It giver various options to create events and occurrences
Documentation is here:- http://django-scheduler.readthedocs.io/en/latest/
I have a model known as Product in Django. Which is defined as below
`class Products(models.Model):
product_choice = (
('1' ,'sightseeing'),
('2','daytour'),
('3','activity'),
('3','experience'),
('4','rentals'),
('3','multidaytrip'),
)
product_type = models.CharField(max_length=20,choices=product_choice, null=True)
category = models.ForeignKey(Category, null=True)
title = models.CharField(max_length=100, blank=True, default='')
pic1 = models.ImageField(upload_to='media', default='media/ross-island-2.jpg')
pic2 = models.ImageField(upload_to='media', default='media/ross-island-2.jpg')
pic3 = models.ImageField(upload_to='media', default='media/ross-island-2.jpg')
shared_code = models.BooleanField(blank=True, default=False)
age_requirements = models.CharField(max_length=100, blank=True, default='')
time_slots = models.CharField(max_length=100 ,blank=True, default='')
location = models.CharField(max_length=100 ,blank=True, default='')
duration = models.CharField(max_length=100 ,blank=True, default='')
affiliated_institutions = models.CharField(max_length=100, null=True)
includes = models.TextField(blank=True)
excludes = models.TextField(blank=True)
medical_requirements = models.CharField(max_length=100, blank=True, default='')
perks_included = models.CharField(max_length=100, blank=True, default='')
product_detail = models.TextField()
vender_name = models.CharField(max_length=100, blank=False)
user = models.ManyToManyField(settings.AUTH_USER_MODEL)
vendor_id = models.IntegerField(blank=True)
about_vender = models.TextField()
price = models.IntegerField(default=0)
child_price = models.IntegerField(default=0)
infant_price = models.IntegerField(default=0)
product_detail = models.TextField(blank=True)
slug = models.SlugField(unique=True, blank=True)
total_slots = models.IntegerField(blank=True, null=True)
open_slots = models.IntegerField(blank=True , null=True)
cancellation_policy = models.TextField(blank=True)
def __unicode__(self):
return str(self.title)
def __str__(self):
return str(self.title)
`
I have installed the Django-Scheduler in my Django Application, however it is installed as a separate app.
I am using Django Rest Framework(DRF) and doing all these alterations via DRF.
class ProductListAPIView(ListAPIView):
queryset = Products.objects.all()
permission_classes = (IsAdminOrReadOnly, )
serializer_class = ProductSerializer
def get_queryset(self):
return Products.objects.all()
def get(self, request, format=None):
snippets = Products.objects.all()
serializer_class = ProductSerializer(snippets, many=True)
return Response(serializer_class.data)
def post(self, request, format=None):
serializer = ProductSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
`
Now I need to create events with the help of Django-Scheduler while creating the Product when a new request comes via Django Rest Framework.
Thanks in anticipation, Please let me know if I am missing on any part.

Django Restful_Api post Json for more than one record in a time

I use Django Restful Api ,I want to post records(more than one record!) in a time ,Models ,serialize,viewset are as follows
Does anyone has some advice? thanks advcance!
model
class Brand(models.Model):
Company_Group = models.ManyToManyField(Company)
Brand_Group = models.CharField(u'Brand Group',max_length=255, default="")
Pref_Brand_Name_Flg = models.CharField(u'Preferred Brand Name Flag',max_length=255, default="")
Pref_Brand_Name = models.CharField(u'Preferred Brand Name',max_length=255, default="")
PrimaryContact = models.ForeignKey(UserRole, null=True, blank=True) #primarybroker
Protect_period = models.CharField(u'Protect period',max_length=255, default="")
# Pref_Brand_Name = models.CharField(u'Preferred Brand Name',max_length=255, default="")
Brand_Name = models.CharField(u'Brand Name',max_length=255, default="")
Brand_Name_SC = models.CharField(u'Brand Name in Local Language',max_length=255, default="")
Year_Enter_Market = models.CharField(u'Entered Market in (Year)',max_length=255, default="")
Category_Display = models.CharField(u'Category Display',max_length=255, default="")
Category_1_Code = models.CharField(u'Category',max_length=255, default="")
Category_2_Code = models.CharField(u'Sub Category',max_length=255, default="")
Price_Low = models.CharField(u'Price Range - Low',max_length=255, default="")
Price_High = models.CharField(u'Price Range - High',max_length=255, default="")
Size_Low = models.CharField(u'Typical Store Size - Low',max_length=255, default="")
Size_High = models.CharField(u'Typical Store Size - High',max_length=255, default="")
Headerquater = models.CharField(u'Headerquater',max_length=255, default="")
Status = models.CharField(u'Status',max_length=255, default="")
Created_On = models.DateField(u'Created On',auto_now_add=True)
Created_By = models.CharField(u'Created By',max_length=255, default="")
Modified_On = models.DateField(u'Modified On', auto_now=True)
Modified_By = models.CharField(u'Modified By',max_length=255, default="")
Agreement_InPlace_Flg = models.CharField(u'TR Agreement in place?',max_length=20, default="")
Web_Site = models.CharField(u'Web Site',max_length=20, default="")
Comment = models.CharField(u'Comment',max_length=20, default="")
viewset
class BrandViewSet(viewsets.ModelViewSet):
queryset = Brand.objects.all()
serializer_class = BrandSerializer
Serializer
class BrandSerializer(serializers.HyperlinkedModelSerializer):
PrimaryContact_id = serializers.ReadOnlyField(source='PrimaryContact.id', read_only=True)
def __init__(self, *args, **kwargs):
many = kwargs.pop('many', True)
super(BrandSerializer, self).__init__(many=many, *args, **kwargs)
class Meta:
model = Brand
fields = data_export_setting.Brand_form_stand # +options ??
#Brand_detail = serializers
"myTest code" :a.py
item = [{"id":"2","PrimaryContact_id":"00000","Pref_Brand_Name_Flg":"00000","Protect_period":"test_for_Protect_period_1","Pref_Brand_Name":"Test","Brand_Name":"Chanel Group","Brand_Name_SC":"test","Year_Enter_Market":"test","Category_Display":"test","Category_1_Code":"api","Category_2_Code":"api","Price_Low":"test","Price_High":"test","Size_High":"test","Headerquater":"test","Status":"test","Created_On":"2017-06-14","Modified_By":"2017-07-08","Modified_On":"000"},{"id":"3","PrimaryContact_id":"1111","Pref_Brand_Name_Flg":"11111","Protect_period":"ppppp","Pref_Brand_Name":"Test","Brand_Name":"Chanel Group 2","Brand_Name_SC":"test","Year_Enter_Market":"test","Category_Display":"test","Category_1_Code":"api","Category_2_Code":"api","Price_Low":"test","Price_High":"test","Size_High":"test","Headerquater":"test","Status":"test","Created_On":"2017-06-14","Modified_By":"2017-07-08","Modified_On":"000"}]
data=json.dumps(item)
def test_get_user_list_3():
resp = requests.post(urlname,auth=AUTH,data=data,headers={ "Content-Type":"application/json","Accept": "application/json"})
test_get_user_list_3()
if item as for one record ,it works
item ={"id":"1","PrimaryContact_id":"00000","Pref_Brand_Name_Flg":"00000","Protect_period":"test_for_Protect_period_1","Pref_Brand_Name":"Test","Brand_Name":"Chanel Group","Brand_Name_SC":"test","Year_Enter_Market":"test","Category_Display":"test","Category_1_Code":"api","Category_2_Code":"api","Price_Low":"test","Price_High":"test","Size_High":"test",Headerquater":"test","Status":"test","Created_On":"2017-06-14","Modified_By":"2017-07-08","Modified_On":"000"},
Ok, i've spent a considerable amount of time trying to get this work. Below is the code that i've used to get this to do bulk creates.
The get_serializer method that's used by default for ModelViewSet passes in the data without many=True so you have to override it and make sure you check the request for a list instead of a dictionary.
That's the only change required to be able to bulk create items from a list.
models.py
class Brand(models.Model):
# ------------------------------------------
# Relations
# ------------------------------------------
Company_Group = models.ManyToManyField(Company)
PrimaryContact = models.ForeignKey(User, null=True, blank=True)
# ------------------------------------------
# Attributes
# ------------------------------------------
# Brand attrs
Brand_Name = models.CharField(u'Brand Name',max_length=255, blank=True)
Brand_Group = models.CharField(u'Brand Group',max_length=255, blank=True)
Pref_Brand_Name = models.CharField(u'Preferred Brand Name',max_length=255, blank=True)
Brand_Name_SC = models.CharField(u'Brand Name in Local Language',max_length=255, blank=True)
Pref_Brand_Name_Flg = models.CharField(u'Preferred Brand Name Flag',max_length=255, blank=True)
# Record management attrs
Modified_On = models.DateField(u'Modified On', auto_now=True)
Created_On = models.DateField(u'Created On', auto_now_add=True)
Created_By = models.CharField(u'Created By', max_length=255, blank=True)
Modified_By = models.CharField(u'Modified By', max_length=255, blank=True)
# Category attrs
Category_1_Code = models.CharField(u'Category', max_length=255, blank=True)
Category_2_Code = models.CharField(u'Sub Category', max_length=255, blank=True)
Category_Display = models.CharField(u'Category Display',max_length=255, blank=True)
# Pricing attrs
Price_Low = models.CharField(u'Price Range - Low', max_length=255, blank=True)
Price_High = models.CharField(u'Price Range - High', max_length=255, blank=True)
# Store attrs
Size_Low = models.CharField(u'Typical Store Size - Low', max_length=255, blank=True)
Size_High = models.CharField(u'Typical Store Size - High', max_length=255, blank=True)
# Company attrs
Status = models.CharField(u'Status', max_length=255, blank=True)
Comment = models.CharField(u'Comment', max_length=20, blank=True)
Web_Site = models.CharField(u'Web Site', max_length=20, blank=True)
Headerquater = models.CharField(u'Headerquater', max_length=255, blank=True)
Protect_period = models.CharField(u'Protect period', max_length=255, blank=True)
Year_Enter_Market = models.CharField(u'Entered Market in (Year)', max_length=255, blank=True)
Agreement_InPlace_Flg = models.CharField(u'TR Agreement in place?', max_length=20, blank=True)
def __str__(self):
return self.Brand_Name
class Meta:
db_table = 'brand'
serializers.py
class BrandSerializer(serializers.ModelSerializer):
class Meta:
model = Brand
fields = '__all__'
views.py
class BrandViewSet(viewsets.ModelViewSet):
model = Brand
serializer_class = BrandSerializer
queryset = Brand.objects.all()
def get_serializer(self, *args, **kwargs):
if 'data' in kwargs:
data = kwargs['data']
if isinstance(data, list):
kwargs['many'] = True
return super().get_serializer(*args, **kwargs)
urls.py
from rest_framework.routers import DefaultRouter
from .views import BrandViewSet
router = DefaultRouter()
router.register(r'brand', BrandViewSet)
urlpatterns = router.urls
I sent the data(JSON) using postman in this format:
[
{
"Brand_Name":"",
"Brand_Group":"",
"Pref_Brand_Name":"",
"Brand_Name_SC":"",
"Pref_Brand_Name_Flg":"",
"Created_By":"",
"Modified_By":"",
"Category_1_Code":"",
"Category_2_Code":"",
"Category_Display":"",
"Price_Low":"",
"Price_High":"",
"Size_Low":"",
"Size_High":"",
"Status":"",
"Comment":"",
"Web_Site":"",
"Headerquater":"",
"Protect_period":"",
"Year_Enter_Market":"",
"Agreement_InPlace_Flg":"",
"PrimaryContact":null,
"Company_Group":[
1
]
},
{
"Brand_Name":"",
"Brand_Group":"",
"Pref_Brand_Name":"",
"Brand_Name_SC":"",
"Pref_Brand_Name_Flg":"",
"Created_By":"",
"Modified_By":"",
"Category_1_Code":"",
"Category_2_Code":"",
"Category_Display":"",
"Price_Low":"",
"Price_High":"",
"Size_Low":"",
"Size_High":"",
"Status":"",
"Comment":"",
"Web_Site":"",
"Headerquater":"",
"Protect_period":"",
"Year_Enter_Market":"",
"Agreement_InPlace_Flg":"",
"PrimaryContact":null,
"Company_Group":[
1
]
}
]
As shown in DRF documentation you can utilize the ListSerializer to create multiple instances of the model.
Your best bet is to create a separate serializer(ListSerializer) with an your own custom .create() method for creating multiple instances of your model. Then in your view you write some business logic to check if it's a single object or a list of multiple objects and send them to the appropriate serializer for creation. Make sure you take a look at the ListSerializer and how to use many=True.
You can potentially use the same serializer with your own custom .create() method and have the business logic inside of there but look at the documentation and see the recommended way of creating multiple instances of objects.

methods in django admin

I have two models, Client and PaymentOptions.
class Client(models.Model):
name = models.CharField(max_length=50, null=True, unique=False)
contact = models.CharField(max_length=50, null=True, unique=False)
address = models.CharField(max_length=300, null=True, unique=False)
class ClientPaymentOption(models.Model):
name = models.CharField(max_length=30, null=True, unique=False, choices=CARD_TYPE)
action = models.CharField(max_length=30, null=True, unique=False, choices=CLIENT_PAYMENT_OPTION)
percent = models.FloatField(max_length=10, null=True, unique=False)
fixamount = models.FloatField(max_length=20, null=True, unique=False)
itemcharged = models.CharField(max_length=10, null=True, unique=False)
In my admin.py, I just want to have when I create a new Client, it will also create it's ClientPaymentOption.
I have this in my admin.py:
admin.site.disable_action('delete_selected')
class ClientAdmin(admin.ModelAdmin):
#display list
list_display = ('name','b_type','banner','logo',
'contact','address','account_type',
'status','currency','color','user',
)
#display fields
fields = ('name','b_type','banner','logo','contact',
'address','account_type','status',
'currency','color','user',
)
pass
admin.site.register(Client, ClientAdmin)
I have done this in my views.py,
client = Client.objects.create( .... )
ClientPaymentOption.objects.create( ...., client=client )
but i dont have any idea to do this in django admin.
do anyone have an idea about my situation? thanks in advance ...
You can override standard django-admin change_view and add ClientPaymentOption.objects.create( ...., client=client )
there.
A short example from django docs:
class MyModelAdmin(admin.ModelAdmin):
# A template for a very customized change view:
change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'
def get_osm_info(self):
# ...
pass
def change_view(self, request, object_id, extra_context=None):
extra_context = extra_context or {}
extra_context['osm_data'] = self.get_osm_info()
return super(MyModelAdmin, self).change_view(request, object_id,
extra_context=extra_context)

Categories

Resources