I am getting this type result from query object:
report_qs = CustomReport.objects.all().filter(id=report_id)
[<CustomReport: {'Name': 'Zara', 'Age': 7, 'Class': 'First'}>]
CustomReport Model:
class CustomReport(models.Model):
"""
Save the result of the custom report form wizard for further
regeneration. The result is saved as a serialized dictionary.
"""
class Meta:
unique_together = (('creation_date', 'name'),)
name = models.CharField(max_length=64)
query = models.TextField()
creation_date = models.DateTimeField(default=datetime.datetime.now,
editable=False)
def __unicode__(self):
return self.query
How to get values and keys?
You Should try
report_qs = CustomReport.objects.all().filter(id=report_id).values('name', 'age', 'class')
Now see report_qs you can easily get values and keys.
You can iterate report_qs
for obj in report_qs:
print obj.keys()
print obj.values()
Related
models.py:
class Balance_Sheet(models.Model): #name of the table
# date = models.DateField() # Name of the column
# transaction_type = models.CharField(max_length=100,blank=False)
# num = models.IntegerField()
name = models.CharField(max_length=100,blank=True)
# description = models.CharField(max_length=100,blank=True)
split = models.CharField(max_length=100,blank=False)
# class Meta:
# abstract : True
class Account_List(models.Model):
account = models.CharField(max_length=100,blank=True,null=True)
type = models.CharField(max_length=100,blank=True, null=True)
split =models.ForeignKey(Balance_Sheet,null=False, default=True,on_delete=models.CASCADE)
def __str__(self):
return 'Account : {0} Type : {1} '.format(self.account,self.type)
views.py:
def DisplayUVL(request):
# Excel page changes
Ven_list = Balance_Sheet.objects.filter(account_list__isnull=True).values_list('split', flat=True)
print("SQL Query:",Ven_list.query)
context = {
'items': Ven_list
# 'header': 'Vendor List'
}
return render(request, 'services2.html', context)
select_relations might be helpful to you to compare two table information and get the common one. select_relations is the native way.
If you are using postgressql you can use inner join SQL queries directly.
This question might helpful for you.
Using the Django REST Framework 2.2, I have a Person model as follows in models.py::
class Person(models.Model):
id = models.CharField(max_length = 20, primary_key = True, blank = True)
name = Models.CharField(max_length = 1024, blank = True)
values = {}
#staticmethod
def create_person(personData):
person = Person(
name = personData.get("name", "Unknown"),
values = personData.get("values", {}),
)
return person
All data is stored in a Firestore database for saving and retrieving data via the REST API. Before new entries are made into the database, a serializer is used to validate incoming POST data.
The route /person takes POST request data and runs it by the PersonCreateSerializer in
views.py:
def create_person(request):
"""
Route: /person
Method: POST
"""
try:
print(request.data)
# Above print outputs:
# <QueryDict: {'name': ['John Doe'], 'values': ['{ "height": 180 }']}>
serializer = PersonCreateSerializer(data = request.data)
serializer.is_valid(raise_exception = True)
person = Person.create_person(request.data)
...
except APIException as exception:
return JsonResponse(exception.APIError, status = exception.status)
serializers.py:
class PersonCreateSerializer(CreateModelSerializer):
class Meta:
model = Person
fields = "__all__"
def validate(self, data):
print(data)
# Above print outputs:
# OrderedDict([('name', 'John Doe')])
# Notice missing 'values' field.
if not data.get("values"): # Ensure we have a values field within the data.
raise APIException("ERROR_MISSING_FIELD", "Missing required field 'values'.", 400)
return data
The problem is however any value provided for the values dictionary is discarded when the serializer validate() function receives it.
POST Payload:
My question is why is the dictionary received from the POST request not received by the serializer so it can be parsed? What is the correcy way to create dictionary fields in Django?
Sent to Serializer:
<QueryDict: {'name': ['John Doe'], 'values': ['{ "height": 180 }']}>
Received by Serializer:
OrderedDict([('name', 'John Doe')])
The problem with JSONField and HStoreField
I have looked at alternatives mentioned such as HStoreField and JSONField however this data is being stored in a Firestore database and the key-value association needs to be retained rather than it being stored as a plain JSON string.
Because the data is being stored in Firestore, the structure of the dictionary array needs to be retained as a map in the database, this allows it to be indexed and queried with Firestore queries.
If we use JSONField, this simply converts the value to a string and removes this functionality.
I believe it is because values is not a field. It is just a class variable.
Serializer filters the data by fields you have pointed to. And you pointed to __all__ which means all fields in model.
You can try:
fields = ['name', 'values']
And if it didn't work, make a function and pass it "as a field":
# models.py
class Person(models.Model):
id = models.CharField(max_length = 20, primary_key = True, blank = True)
name = Models.CharField(max_length = 1024, blank = True)
values = {}
def get_values(self):
return self.values
# serializers.py
class PersonCreateSerializer(CreateModelSerializer):
class Meta:
model = Person
fields = ['name', 'get_values']
The solution I found was to make use of the django-dictionaryfield module, this provides a Dictionary field type that can be used for converting to and from all array types, such as dictionaries and lists.
Without a field declared in the model.py, the serializer ignores it since it isn't considered part of the model itself, therefore using a custom DictionaryField model allows it to be stored as a Django model field.
Django DictionaryField Setup
Install the module into your project:
$ pip install django-dictionaryfield
Add dictionaryfield into your INSTALLED_APPS in the Django configuration file:
INSTALLED_APPS = (
...
"dictionaryfield",
)
Model Class
Use the DictionaryField for fields that should be arrays.
from django.db import models
from dictionaryfield import DictionaryField
class Person(models.Model):
id = models.CharField(max_length = 20, primary_key = True, blank = True)
name = Models.CharField(max_length = 1024, blank = True)
values = DictionaryField(default = {})
#staticmethod
def create_person(personData):
person = Person(
name = personData.get("name", "Unknown"),
values = personData.get("values", {}),
)
return person
Hi guys so I have a search function but when using the .objects.filter() method I get a queryset that shows an ID instead of the username.
This is the view:
def search_expense(request):
if request.method == 'POST':
search_str = json.loads(request.body).get('searchText')
expenses = Expense.objects.filter(
amount__istartswith=search_str) | Expense.objects.filter(
date__icontains=search_str) | Expense.objects.filter(
description__icontains=search_str) | Expense.objects.filter(
category__icontains=search_str)
data = expenses.values()
return JsonResponse(list(data), safe=False)
<QuerySet [{'id': 16, 'amount': 2.33, 'date': datetime.date(2020, 10, 2), 'description': 'Something', 'owner_id': 1, 'category': 'Food'}]>
So instead of the 'owner_id': 1 I need it to be 'owner': username
The model (the User model is Django's standard model):
class Expense(models.Model):
amount = models.FloatField()
date = models.DateField(default=now)
description = models.TextField()
owner = models.ForeignKey(to=User, on_delete=models.CASCADE)
category = models.CharField(max_length=255)
def __str__(self):
return self.category
class Meta:
ordering: ['-date']
You can add new fields to .values().
from django.db.models import F
fields = tuple(x.name for x in Expense._meta.get_fields())
data = expenses.values(*fields, owner_name=F("owner__value"))
You will also have to specify all the fields you want manually, or if you want all the fields then you can just use .get_fields() like I have done.
You have to name the new field something other than "owner", or you will get a ValueError:
ValueError: The annotation 'owner' conflicts with a field on the model.
Showing the ID of ForeignKey fields is the intended behaviour of .values() according to the documentation:
If you have a field called foo that is a ForeignKey, the default values() call will return a dictionary key called foo_id, since this is the name of the hidden model attribute that stores the actual value (the foo attribute refers to the related model).
If I have a APIQuery object, that gives me the following representation:
{
'key': 'Foo',
'field_1': 'John',
'field_2': 'Doe',
}
And I am trying to store it with a model, like
class Person(models.Model):
key = models.CharField(max_length=255, primary_key=True)
first = models.CharField(max_length=255)
last = models.CharField(max_length=255)
How do I properly setup a serializer, with the constraint that the keys in the APIQuery object are subject to change, e.g. field_1 could become field_17. I know that without that last constraint I could just do
class PersonSerializer(serializers.ModelSerializer):
key = serializers.CharField()
field_1 = serializers.CharField(source='first')
field_2 = serializers.CharField(source='last')
Use SerializerMethodField and define function get_last_namewhich will return last name.
class PersonSerializer(serializers.ModelSerializer):
key = serializers.CharField()
field_1 = serializers.SerializerMethodField('get_first_name')
field_2 = serializers.SerializerMethodField('get_last_name')
class Meta:
model = "Person"
fields = ('key','field_1','field_2')
def get_first_name(self, obj):
return obj.first
def get_last_name(self, obj):
return obj.last
I have these serializers in my app:
class ScheduleSerializer(serializers.ModelSerializer):
class Meta:
model = Schedule
fields = ('id',)
class DisciplineSerializer(serializers.ModelSerializer):
class Meta:
model = Discipline
fields = ('id',)
class WriteTeacherSerializer(serializers.ModelSerializer):
disciplines = DisciplineSerializer(many=True)
schedules = ScheduleSerializer(many=True)
class Meta:
model = Teacher
fields = ('phone_number', 'bio', 'price', 'disciplines', 'schedules')
depth = 1
def update(self, instance, validated_data):
print "\n"
#Debugging here
print validated_data
print "\n"
print instance.__dict__
print "\n"
instance.phone_number = validated_data['phone_number']
instance.bio = validated_data['bio']
instance.price = validated_data['price']
disciplines = validated_data.pop('disciplines')
schedules = validated_data.pop('schedules')
for discipline in disciplines:
try:
stored_discipline = Discipline.objects.get(id=discipline['id'])
instance.disciplines.add(stored_discipline)
except Discipline.DoesNotExist:
raise Http404
for schedule in schedules:
try:
stored_schedule = Schedule.objects.get(id=schedule['id'])
instance.schedules.add(stored_discipline)
except Discipline.DoesNotExist:
raise Http404
instance.save()
return instance
As you can see I am trying a nested serialization with the fields schedules and disciplines. I think I followed the documentation, but the nested serialization is not working when I test it. I printed the instance and validated_data objects and tested it on the shell.
I start the data in this format:
data = {u'phone_number': u'+99999999999', u'bio': u'BIO', u'price': 40, u'disciplines': [{'id': 1}], u'schedules': [{'id': 2}]}
I got a teacher instance and started the serializer like this:
serializer = WriteTeacherSerializer(teacher, data=data)
It shows True on a serializer.is_valid() call.
However when I try to save it the validated_data and the instance.__dict__ are like that:
#validated_data
{u'phone_number': u'+5584998727770', u'bio': u'BIO', u'price': 40, u'disciplines': [OrderedDict()], u'schedules': [OrderedDict()]}
#instance.__dict__
{'phone_number': u'', 'bio': u'', 'price': 50, 'profile_id': 2, '_state': <django.db.models.base.ModelState object at 0xb64a6bec>, 'id': 6}
They don't seem to notice the nested fields wich makes the update() method not work.
Am I doing something wrong?
Here is my Teacher Model as well:
class Teacher(models.Model):
price = models.IntegerField(default=50)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Wrong phone number format.")
phone_number = models.CharField(validators=[phone_regex], max_length=15, blank=True)
profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
schedules = models.ManyToManyField(Schedule, related_name='schedules')
disciplines = models.ManyToManyField(Discipline, related_name='disciplines')
bio = models.CharField(max_length=200, blank=True)
If you are just sending IDs then you don't need to add the nested serializer, just specify the field name of the ForeignKey or ManyToManyField.
class WriteTeacherSerializer(serializers.ModelSerializer):
class Meta:
model = Teacher
fields = ('phone_number', 'bio', 'price', 'disciplines', 'schedules')
I am also wondering if it is because you have a depth=1 flag?
DRF doesn't support nested updates out of the box. You have to override the Serializer's update method, and write your own update logic, so you'd be seeing an error for this warning if you were sending nested data.