Get JSON data (Django) - json

This my model
Driver Model
class Driver(models.Model):
named = models.CharField(max_length=150)
ident = models.CharField(max_length=100, null=True, blank=True)
def __unicode__(self):
return self.named
manufacture model
class Carlcid(models.Model):
namec = models.CharField(max_length=100)
lc_id = models.CharField(max_length=100, null=True, blank=True)
def __unicode__(self):
return unicode(self.namec)
Car model
class Car(models.Model):
f_idcar = models.ForeignKey(Carlcid, related_name='carlcd')
id_driver = models.ForeignKey(Driver)
def __unicode__(self):
return unicode(self.f_idcar)
This My views
def get_name_driver(request):
name = request.GET.get('name')
query = Car.objects.filter(f_idcar__namec=name)
results=[]
for q in query:
m_json={}
m_json['nama']= q.named
results.append(m_json)
return HttpResponse(results,"application/json")
i get {'nama': <Driver: Michael>}
but i wont get result like this {'nama': "Michael"}, How to get result like that, thanks for help.

You must get the driver name with the following line :
m_json['nama']= q.id_driver.named
Your new view :
def get_name_driver(request):
name = request.GET.get('name')
query = Car.objects.filter(f_idcar__namec=name)
results=[]
for q in query:
m_json={}
m_json['nama']= q.id_driver.named
results.append(m_json)
return HttpResponse(results,"application/json")
In addition to my answer, I want give you an advice :
You should named your foreign key like the model. Yes, in database it will be store the driver id, but when you use Django ORM, you don't get the id of driver but a Driver object.
So I advise you to rename id_driver by driver so you will use
m_json['nama']= q.driver.named
but it's not required, just advise ;)

Related

To return custom field in DjangoRestFramework after aggregation

There are lot of answers related to custom fields on stackoverflow but when trying with them, I am getting different error, so posting a separate question.
I wanted to return a JSON Response for the following url
urls.py
path('cards/<int:pk>/smarts', smarts.as_view(), name="smarts"),
I will be using below api.py file to return aggregate fields using Transaction model, the query is working fine, I only have to return appropriate response. Here I have one of the fields as Decimal hence tried with DjangoJSONEncoder but got an error.
api.py
class smarts(generics.ListAPIView):
serializer_class = TransactionSerializer
permission_classes = [permissions.IsAuthenticated, TransactionIsOwnerOrNot]
def get_queryset(self):
card = get_object_or_404(self.request.user.cards, pk=self.kwargs['pk'])
qs=card.transactions.values('vendor').annotate(a=Count('pk'),b=Sum('amount')).order_by('-b')
....CODE REQUIRED
return ....
models.py
class Transactions(models.Model):
amount = models.DecimalField(max_digits=19, decimal_places=2)
vendor = models.CharField(max_length=200)
category = models.CharField(max_length=200)
owner = models.ForeignKey(Cards, on_delete=models.CASCADE, related_name="transactions",null=True)
serializer.py
class TransactionSerializer(serializers.ModelSerializer):
class Meta:
model = Transactions
fields = '__all__'
I found the answer after hit and trial, I used custom serializer to return required field.
serializer.py
class SmartSerializer(serializers.Serializer):
vendor = serializers.CharField(max_length=200)
tot = serializers.IntegerField()
tot_amt = serializers.DecimalField(max_digits=19, decimal_places=2)
api.py
class smartstatements(generics.ListAPIView):
permission_classes = [permissions.IsAuthenticated, TransactionIsOwnerOrNot]
serializer_class = SmartSerializer
def get_queryset(self):
card = get_object_or_404(self.request.user.cards, pk=self.kwargs['pk'])
queryset=card.transactions.values('vendor')
.annotate(tot=Count('pk'),tot_amt=Sum('amount'))
.order_by('-tot_amt')
return queryset

Django: how to create an instance of the model based on the data from the json file?

In the project there is a model with existing instances in the database.
class Instagram(models.Model):
userid = models.CharField(max_length=255, unique=True)
username = models.CharField(max_length=50, blank=True, null=True)
full_name = models.CharField(max_length=50, blank=True, null=True)
avatar = models.URLField(max_length=255, blank=True, null=True)
bio = models.CharField(max_length=255, blank=True, null=True)
.....
.....
There is another model, so far without instaces
class InstagramDemographicsAnalitics(models.Model):
instagram = models.ForeignKey(Instagram, related_name='demographics')
age_group = models.CharField(max_length=10)
gender = models.CharField(max_length=10, default='female')
viewer_percentage = models.DecimalField(default=0, max_digits=5, decimal_places=2)
It is necessary from the file statistic.json, which is in the same folder with the project, to take the data for the corresponding userid and on their basis create the instances of the model InstagramDemographicsAnalitics.
I have no idea how to do this. I really need advice with a sequence of actions and if possible code example.
As an example, this function would take an instance of Instagram and return an instance of InstagramDemographicsAnalitics:
def get_ida_instance(instagram):
# Load all users from JSON file
all_users = json.load('example.json')
# Find the one user, this depends on the format of your JSON file
my_user = [x for x in all_users if x['userid'] == instagram.userid][0]
# Map the JSON fields to your Model
ida = InstagramDemographicsAnalitics()
ida.instagram = instagram
ida.age_group = my_user['age_group']
ida.gender = my_user['gender']
ida.viewer_percentage = float(str(my_user['viewer_percentage']))
ida.save() # If you want to persist it to the database
# Return the instance
return ida
It depends of course on the actual format of your JSON file.

Why i cant save my form to my database? Many to many, django

I have an issue here. I have my form with one field (many to many), this field maps to a m2m table with the atributes id_academic_degree id_employee and license. When i try to save it, django displays an error like this
Cannot set values on a ManyToManyField which specifies an intermediary model. Use employees.EmployeeAcademicDegree's Manager instead.
View
CreateEmployee(CreateView):
model = Employee
form_class = EmployeeForm
template_name = 'CreateEmployee.html'
#transaction.atomic
def form_valid(self, form):
form.save()
form.save_m2m()
messages.success(self.request, 'El Empleado fue guardado Exitosamente.')
return HttpResponseRedirect(self.get_success_url())
def get_success_url(self):
return reverse('physicians:CreatePerson',)
my model
class Employee(models.Model):
person = models.OneToOneField(Person)
region = models.ForeignKey(Region, db_column='id_region')
academic_degrees = models.ManyToManyField(AcademicDegree,
through='EmployeeAcademicDegree', blank=True)
active = models.NullBooleanField()
rfc = models.CharField(max_length=15, blank=True, null=True)
shift_start = models.TimeField(blank=True, null=True)
shift_end = models.TimeField(blank=True, null=True)
history = HistoricalRecords() # Always leave at the end.
class Meta:
db_table = 'employee'
def __str__(self):
return self.person.full_name
def __unicode__(self):
return self.person.full_name
class EmployeeAcademicDegree(models.Model):
employee = models.ForeignKey(Employee, db_column='id_employee')
academic_degree = models.ForeignKey(AcademicDegree,
db_column='id_academic_degree')
license = models.CharField(max_length=15, blank=True, null=True)
history = HistoricalRecords() # Always leave at the end.
class Meta:
db_table = 'employee_academic_degree'
def __str__(self):
return unicode(self.academic_degree)
def __unicode__(self):
return unicode(self.academic_degree)
And the tables are the following
Employee
id
id_person
id_region
active(boolean)
rfc
shift_start
shift_end
employee_academic_degrees
id_employee_academic_degrees
id_employee(FK)
id_academic_degree(FK)
license
I suppose that i need to save first the relation then the whole object (but i dont know how to save the license, because the form doesnt display any field to fill the license)

depth = 1 doesn't work properly and it's saves Null in ManyToManyField and ForeignKey fields in Django Rest Framework

after adding depth = 1 doesn't work properly
=> models.py file
class State(models.Model):
state_name = models.CharField(max_length = 30, unique=True)
def __unicode__(self):
return str(self.state_name)
class City(models.Model):
state = models.ForeignKey(State, related_name='state_city')
city_name = models.CharField(max_length = 30)
def __unicode__(self):
return str(self.city_name)
class Meta:
ordering = ('city_name',)
unique_together = ('state', 'city_name',)
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
owner = models.ForeignKey('auth.User', related_name='snippets')
state = models.ForeignKey(State,blank=True,null=True)
city = models.ManyToManyField(City)
=> serializers.py file
class StateSerializer(serializers.ModelSerializer):
class Meta:
model = State
class CitySerializer(serializers.ModelSerializer):
state_name = serializers.CharField(source='state.state_name', read_only=True)
class Meta:
model = City
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username', read_only=True)
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'owner', 'state', 'city')
depth = 1
I have added ForeignKey and ManyToManyField fields in state and city respectively. It doesn't save values in SnippetSerializer while added depth = 1 in Meta Class (it saves Null value in state and city fields). When I add depth = 1 JSON showing related fields as it should be but it doesn't work properly while add new Snippet. Without depth = 1 it works fine.
I have complex database where tables has many ManyToMany and ForeignKey related fields. Please give me suggestion so I can get related data in JSON.
I have djangorestframework-3.1.2 version. I have used latest version too but same problem. please give me solution and thanks in advance.
I faced the same problem and managed to solve it. Since the problem is with the depth, I just change the depth value in the init method.
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username', read_only=True)
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'owner', 'state', 'city')
depth = 1
def __init__(self, *args, **kwargs):
super(SnippetSerializer, self).__init__(*args, **kwargs)
request = self.context.get('request')
if request and request.method=='POST':
self.Meta.depth = 0
else:
self.Meta.depth = 1
In the code above, I changed the depth dynamically according to what type of request that I made.
But, this is the workaround that I found myself, I'm not sure if this is the best practice but it solve the problem with just little modification.
depth is only for representation (http://www.django-rest-framework.org/api-guide/serializers/#specifying-nested-serialization). If you want to create/update the related fields too you have to overwrite the create/update methods in the serializer (http://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers).
Greetings.

Django subquery problem "Subquery returns more than 1 row"

I have three related models like
class City(models.Model):
name = models.CharField(max_length=200, blank=False)
country = models.ForeignKey(Country,unique=False,null=False)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
class County(models.Model):
name = models.CharField(max_length=500, blank=False)
city = models.ForeignKey(City,unique=False,null=False)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
class District(models.Model):
name = models.CharField(max_length=500, blank=False)
county = models.ForeignKey(County,unique=False,null=False)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
What I'd like to do is getting all the Districts for a specified city.
I tried :
District.objects.all().filter(county = County.objects.all().filter(city=City.objects.filter(id=4)))
However, it gives error like OperationalError: (1242, 'Subquery returns more than 1 row')
Can you give me any idea how I can achive this query in django ?
Thanks
I'm not sure why you're complicating things by doing them that way. You could get away with something along the lines of:
For a given instance city of the model City, you can get all Districts in this way:
District.objects.filter(county__city=city)
You may want to go through this section on the Django documentation called Lookups that span relationships as it explains how you can achieve similar lookup queries.