I try to serialize query set
def do(self):
reservations = Reservation.objects.all()
serializer = ReservationSerializer(data=reservations, many=True)
if serializer.is_valid():
encoded_data = json.dumps(serializer.data)
r = requests.post('http://httpbin.org/post', headers={'Content-Type': 'application/json'}, data=encoded_data)
print(r.text)
else:
print(serializer.errors)
And I always get error of
{u'non_field_errors': [u'Expected a list of items but got type "QuerySet".']}
I tried to use values() on query set, and then convert to list, but this way I get objects without nested models
model
class Reservation(models.Model):
start = models.DateField(verbose_name='Заезд', auto_now=False, auto_now_add=False, blank=False)
end = models.DateField(verbose_name='Выезд', auto_now=False, auto_now_add=False, blank=False)
check_in_time = models.TimeField(verbose_name='Время заезда', blank=False)
check_out_time = models.TimeField(verbose_name='Время выезда', blank=False)
has_refund = models.BooleanField(verbose_name='Возвратная бронь', default=True)
payed = models.BooleanField(verbose_name='Оплачено', default=False)
reserved_days = models.ManyToManyField(Day, blank=False)
additional_services = models.ManyToManyField(AdditionalService)
guest_name = models.CharField(verbose_name='Имя гостя', max_length=200, blank=True)
reservation_number = models.CharField(verbose_name='Номер брони', max_length=200, blank=True)
class AdditionalService(models.Model):
payment_date = models.CharField(verbose_name='Дата оплаты', max_length=200, blank=True)
payment_type = models.CharField(verbose_name='Форма оплаты', max_length=200, blank=False)
service = models.CharField(verbose_name='Услуга', max_length=200, blank=False)
quantity = models.IntegerField(blank=False)
price = models.FloatField(blank=False)
class Day(models.Model):
date = models.DateField(auto_now=False, auto_now_add=False)
price = models.FloatField()
payment_method = models.CharField(max_length = 200, blank=True)
payment_date = models.CharField(max_length=200, blank=True)
room = models.ForeignKey(Room, null=True, blank=True, verbose_name='Номер', on_delete=models.CASCADE)
class Room(models.Model):
name = models.CharField(max_length = 200, null=True)
id = models.AutoField(primary_key=True)
room_id = models.CharField(max_length = 200, null=False)
def __unicode__(self):
return self.name
serializers
class ReservationSerializer(serializers.ModelSerializer):
reserved_days = DaySerializer(many=True)
additional_services = AdditionalServicesSerializer(many=True)
class Meta:
model = Reservation
fields = [
'start',
'end',
'check_in_time',
'check_out_time',
'reserved_days',
'additional_services',
'has_refund',
'payed',
'guest_name',
'reservation_number',
]
class DaySerializer(serializers.ModelSerializer):
room = RoomSerializer()
class Meta:
model = Day
fields = [
'date',
'price',
'payment_method',
'payment_date',
'room',
]
class AdditionalServicesSerializer(serializers.ModelSerializer):
class Meta:
model = AdditionalService
fields = [
'payment_date',
'payment_type',
'service',
'quantity',
'price',
]
class RoomSerializer(serializers.ModelSerializer):
class Meta:
model = Room
fields = [
'room_id',
]
For serialization you don't need to use data keyword, just pass queryset as first positional argument:
serializer = ReservationSerializer(reservations, many=True)
return serializer.data
Related
am new to Django and currently trying the Foreign Key concept. I have three models as shown below.
class Basket(models.Model):
basket_name = models.CharField(max_length=5, unique=True)
def __str__(self):
return self.basket_name
class Product(models.Model):
Grams = 'GM'
Kilograms = 'KG'
WeightBased = 'WPG'
QuantityBased = 'CPG'
PRODUCT_UNIT_WT_CHOICES=[
(Grams, 'Grams'),
(Kilograms, 'Kilograms')
]
PRODUCT_TYPE_CHOICES =[
(WeightBased, 'Weight Based Product'),
(QuantityBased, 'Quantity Based Product')
]
product_name = models.CharField(max_length=30, unique=True)
product_description = models.TextField(max_length=300)
product_price = models.DecimalField(max_digits=5, decimal_places=2)
product_unit_weight = models.DecimalField(max_digits=5, decimal_places=2)
product_unit_weight_units = models.CharField(max_length=2, choices=PRODUCT_UNIT_WT_CHOICES, default=Grams)
product_type = models.CharField(max_length=3, choices=PRODUCT_TYPE_CHOICES, default=QuantityBased)
product_image = models.ImageField(upload_to=imageUploadPath, null=True, blank=True)
def __str__(self):
return self.product_name
class BasketProductMapping(models.Model):
basket_reference = models.ForeignKey(Basket, on_delete=models.CASCADE)
product_reference = models.ForeignKey(Product, on_delete=models.CASCADE)
mapped_basket_name = models.CharField(max_length=5,null=False, blank=False)
mapped_product_name = models.CharField(max_length=30, null=False, blank=False)
Here are my serializers:
class ProductSerializer(serializers.ModelSerializer):
product = serializers.CharField(read_only=True)
class Meta:
model = Product
fields = ['id', 'product_name', 'product_description', 'product_price', 'product_unit_weight',
'product_unit_weight_units', 'product_type', 'product_image']
class BasketSerializer(serializers.ModelSerializer):
basket = serializers.CharField(read_only=True)
class Meta:
model = Basket
fields = ('id', 'basket_name')
class BasketProductMappingSerializer(serializers.ModelSerializer):
basket_reference = serializers.CharField(source ='basket.basket_name', read_only=True)
product_reference = serializers.CharField(source='product.product_name', read_only=True)
class Meta:
model = BasketProductMapping
fields = ['id', 'basket_reference', 'product_reference', 'mapped_basket_name', 'mapped_product_name']
What I am trying to achieve is get a list of all the values in 'basket_name' and 'product_name' when I call the BasketProductMappingSerializer. But the output I am getting is this:
{
"status": 1,
"message": "Basket Product Mapping List",
"data": [
{
"id": 1,
"mapped_basket_name": "A1",
"mapped_product_name": "XYZ"
}
]
}
This is my views.py code:
class BasketProductViewSet(APIView):
def get(self, request):
if request.GET.get('id'):
print('Basket Product Mapping Details')
basketProductMappingData = BasketProductMapping.get(id = request.GET.get('id'))
serializer = BasketProductMappingSerializer(basketProductMappingData)
else:
basketProductMappingData = BasketProductMapping.objects.all().values('id', 'basket_reference__basket_name', 'product_reference__product_name', 'mapped_basket_name', 'mapped_product_name')
serializer = BasketProductMappingSerializer(basketProductMappingData, many=True)
response = {'status':1, 'message':"Basket Product Mapping List", 'data':serializer.data}
Where am I going wrong? Sorry if my question is very trivial. Thanks for your help in advance.
i see that there is an error in your views BasketProductMapping.get(id = request.GET.get('id')) should be BasketProductMapping.objects.get(id = request.GET.get('id'))
i don't know if it gonna work but can you try
basket_reference = serializers.ReadOnlyField(source ='basket.basket_name')
product_reference = serializers.ReadOnlyField(source='product.product_name')
instead of
basket_reference = serializers.CharField(source ='basket.basket_name', read_only=True)
product_reference = serializers.CharField(source='product.product_name', read_only=True)
I have the following constellation of Tables, which are linked via FK's:
(omitted a few fields for better readability)
class ProductDetail(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
product_detail = models.CharField(max_length=100, primary_key=True, verbose_name='Product Detail Name')
materialcode = models.CharField(max_length=20, blank=False, null=False, verbose_name='Material-Code')
billing_model = models.ForeignKey(BillingModel, on_delete=models.CASCADE)
....
--------------
class MinimumRevenue(models.Model):
operator = models.ForeignKey(Operator, on_delete=models.CASCADE)
billing_model = models.ForeignKey(BillingModel, on_delete=models.CASCADE)
minimum_revenue = models.DecimalField(decimal_places=2, max_digits=20, verbose_name='Minimum Revenue')
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
product_detail = models.ForeignKey(ProductDetail, on_delete=models.CASCADE, verbose_name='Product Detail')
event_type_assignment = models.CharField(max_length=100, verbose_name='Event Type Assignment')
start_date = models.DateField(blank=False, null=False, verbose_name='Start Date', default=get_first_of_month)
end_date = models.DateField(blank=False, null=False, verbose_name='End Date')
....
And a Table (Django_Tables2) which points to the MinimumRevenue Model (which works as designed), now I would like to also show some more related fields in my Table:
class MinimumRevenueTable(tables.Table):
edit = tables.LinkColumn('non_voice:minimum_revenue_update', orderable=False, text='Edit', args=[A('pk')])
invoice_text = tables.TemplateColumn(
'<data-toggle="tooltip" title="{{record.context}}">{{record.invoice_text|truncatewords:2}}')
start_date = tables.DateColumn(format='Y-m-d')
end_date = tables.DateColumn(format='Y-m-d')
foreigncolumn = tables.Column(accessor='productdetail.materialcode')
class Meta:
model = MinimumRevenue
template_name = "django_tables2/bootstrap4.html"
fields = ('operator', 'billing_model', 'minimum_revenue', 'product', 'product_detail', 'event_type_assignment',
'start_date', 'end_date', 'invoice_text', 'currency', 'foreigncolumn')
attrs = {'class': 'table table-hover', }
The foreigncolumn column is never filled, just showing '-', I also tried it with other columns of ProductDetail, but never get any result, would really appreciate any solutions!
I'm new on Django Rest Framework and when I want to POST data I get a error: KeyError: 'id_area' I do not know what I'm doing wrong. Here's my code:
in my models.py
class Area(models.Model):
id_area = models.AutoField(primary_key=True)
APM = 'apm'
BUSINESS = 'business'
DESARROLLO = 'desarrollo'
SISTEMAS = 'sistemas'
ATENTUSIANOS_CHOICES = (
(APM, 'Apm'),
(BUSINESS, 'Business'),
(DESARROLLO, 'Desarrollo'),
(SISTEMAS, 'Sistemas'),
)
nombre = models.CharField(max_length=255, choices=ATENTUSIANOS_CHOICES)
class Meta:
verbose_name = 'Área'
verbose_name_plural = 'Áreas'
def __str__(self):
return self.nombre
class Atentusiano(models.Model):
id_atentusiano = models.AutoField(primary_key=True)
nombre = models.CharField(max_length=255, blank=False, null=False)
apellido = models.CharField(max_length=255, blank=False, null=False)
correo = models.CharField(max_length=255, blank=False, null=False, unique=True)
anexo = models.CharField(max_length=255, blank=True, null=True)
area = models.ForeignKey(Area, related_name='areas', on_delete=models.CASCADE)
class Meta:
verbose_name = 'Atentusiano'
verbose_name_plural = 'Atentusianos'
ordering = ['nombre']
def __str__(self):
return self.nombre + ' ' + self.apellido
in my serializers.py
class AreaSerializer(serializers.ModelSerializer):
areas = serializers.CharField(read_only=True)
class Meta:
model = Area
fields = ('id_area', 'nombre', 'areas')
class AtentusianoSerializer(serializers.ModelSerializer):
atentusianos = serializers.CharField(read_only=True)
area = serializers.CharField(source='area.nombre', read_only=True)
id_area = serializers.CharField(source='area.id_area')
class Meta:
model = Atentusiano
fields = ['id_atentusiano', 'nombre', 'apellido', 'correo', 'anexo', 'id_area', 'area', 'atentusianos']
def create(self, validated_data):
area_data = validated_data.pop('id_area')
area = models.Area.objects.create(**area_data)
atentusiano = models.Atentusiano.objects.create(area=area, **validated_data)
return atentusiano
And in my views.py
class AtentusianoView(viewsets.ModelViewSet):
queryset = Atentusiano.objects.all()
serializer_class = AtentusianoSerializer
class AreaView(viewsets.ModelViewSet):
queryset = Area.objects.all()
serializer_class = AreaSerializer
The problem is that when I want to Post data, for example:
{
"nombre": "name",
"apellido": "lastname",
"correo": "email#gmail.com",
"anexo": "1364",
"id_area": "1"
}
i got this error area_data = validated_data.pop('id_area')
KeyError: 'id_area'
I need help please
you should pop like this,
class AtentusianoSerializer(serializers.ModelSerializer):
.....
.....
class Meta:
model = Atentusiano
fields = ['id_atentusiano', 'nombre', 'apellido', 'correo', 'anexo', 'id_area', 'area', 'atentusianos']
def create(self, validated_data):
id_area = validated_data.pop('area')['id_area'] # here the correction
area = Area.objects.create(id_area=id_area) # an additional correction
atentusiano = Atentusiano.objects.create(area=area, **validated_data)
return atentusiano
EDIT: As id_area value, you are passing a string instead of an integer which will through another error. Also not,
area = models.Area.objects.create(**area_data)
it should be,
area = Area.objects.create(id_area=id_area)
I have followed this tutorial to implement inlneformset.
CreateView works (data is registered in database) but UpdateView doesn't.
UpdateView is correctly displayed with correct data.
But it seems like subform (application inlineformset) is never valid and I don't understand why?
forms.py:
NAME = Thesaurus.options_list(2,'fr')
ACCESS = Thesaurus.options_list(3,'fr')
ApplicationFormset = inlineformset_factory(
Utilisateur, Application,
fields=('app_app_nom','app_dro'),
widgets={
'app_app_nom': forms.Select(choices=NAME),
'app_dro': forms.Select(choices=ACCESS)
},
extra=3,
can_delete=True,
)
models.py:
class Projet(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
pro_ide = models.AutoField(primary_key = True)
pro_nom = models.IntegerField("Nom du projet", null=True, blank=True)
pro_log = models.CharField("Log utiisateur", max_length=20, null=True, blank=True)
pro_dat = models.DateTimeField("Date log",auto_now_add=True)
pro_act = models.IntegerField("Projet en cours ?", null=True, blank=True)
log = HistoricalRecords()
class Meta:
db_table = 'tbl_pro'
verbose_name_plural = 'Projets'
ordering = ['pro_ide']
permissions = [
('can_add_project','Can add project'),
]
class Utilisateur(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
uti_ide = models.AutoField(primary_key = True)
pro_ide = models.ForeignKey(Projet, on_delete = models.CASCADE) # related project
uti_nom = models.CharField("Nom", max_length=20, null=True, blank=True)
uti_pre = models.CharField("Prénom", max_length=20, null=True, blank=True)
uti_mai = models.CharField("Email", max_length=40, null=True, blank=True)
uti_sit = models.CharField("Equipe", max_length=20, null=True, blank=True)
uti_pro = models.CharField("Fonction/profil", max_length=200, null=True, blank=True)
uti_dem_dat = models.DateTimeField("Date demande",auto_now_add=True, null=True, blank=True)
uti_val = models.IntegerField("Demande validée ?", null=True, blank=True)
uti_val_dat = models.DateTimeField("Date validation",auto_now_add=True, null=True, blank=True)
uti_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
uti_dat = models.DateTimeField("Date log",auto_now_add=True, null=True, blank=True)
log = HistoricalRecords()
#classmethod
def options_list(cls,pro_ide):
projet = Projet.objects.get(pro_ide=pro_ide)
utilisateurs = Utilisateur.objects.filter(pro_ide=projet.pro_ide)
the_opts_list = [(utilisateur.uti_ide, utilisateur.uti_nom+', '+utilisateur.uti_pre) for utilisateur in utilisateurs]
the_opts_list.insert(0, (None, ''))
return the_opts_list
class Meta:
db_table = 'tbl_uti'
verbose_name_plural = 'Utilisateurs'
ordering = ['uti_ide']
class Application(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
app_ide = models.AutoField(primary_key = True)
uti_ide = models.ForeignKey(Utilisateur, on_delete = models.CASCADE) # related utilisateur
app_app_nom = models.IntegerField("Nom application", null=True, blank=True)
app_dro = models.IntegerField("Droit sur application", null=True, blank=True)
app_sta = models.IntegerField("Statut (création/Modification/Suppression", null=True, blank=True)
app_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
app_dat = models.DateTimeField("Date log",auto_now_add=True, null=True, blank=True)
log = HistoricalRecords()
class Meta:
db_table = 'tbl_app'
verbose_name_plural = 'Applications'
ordering = ['app_ide']
class Administration(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
adm_ide = models.AutoField(primary_key = True)
app_ide = models.ForeignKey(Application, on_delete = models.CASCADE) # related application
adm_nom = models.CharField("Nom d'utilisateur dans l'application", max_length=20, null=True, blank=True)
adm_dem = models.IntegerField("Demande traitée ?", null=True, blank=True)
adm_dem_dat = models.DateTimeField("Date traitement de la demande",auto_now_add=True)
adm_log = models.CharField("Log utilisateur", max_length=20, null=True, blank=True)
adm_dat = models.DateTimeField("Date log",auto_now_add=True)
log = HistoricalRecords()
class Meta:
db_table = 'tbl_adm'
verbose_name_plural = 'Adminitrations'
ordering = ['adm_ide']
permissions = [
('can_manage_project','Can manage project'),
]
UpdateView:
class UtilisateurUpdateView(UpdateView):
model = Utilisateur
fields = ['uti_nom','uti_pre','uti_mai','uti_sit','uti_pro']
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
if self.request.POST:
data["utilisateur"] = self.request.user.username
data["application"] = ApplicationFormset(self.request.POST, instance=self.object)
else:
data["application"] = ApplicationFormset(instance=self.object)
return data
def form_valid(self, form):
context = self.get_context_data()
application = context["application"]
self.object = form.save()
self.object.save()
if application.is_valid(): # ***** NEVER VALID *****
application.instance = self.object
print('application.instance',application.instance)
application.app_app_nom = application.instance.cleaned_data['app_app_nom']
application.app_dro = application.instance.cleaned_data['app_dro']
application.app_log = context["utilisateur"]
application.uti_ide = 1
application.save()
return super().form_valid(form)
def get_success_url(self):
return reverse("project:index")
I have resolve my problem: I forget to insert form_set id in my html template (app_ide in my case)
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)