I am trying to fetch data using raw sql query but I am facing issues when I am trying to pass the raw sql response to the Serializer class.
Serializer
class User_Serializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
View
class UserView(APIView):
def get(self, request, emailId, format=None):
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM users")
resRow = cursor.fetchone()
serializerResponse = User_Serializer(resRow)
return Response(serializerResponse.data)
I realise that the Serializer class cannot work with the ModelSerialzier class in this scenerio. How should I build my Serializer considering the fact that I need to post and save data to the concerned model using this Serializer class.
Instead of creating a connection manually use your model manager's raw method. It will return a RawQuerySet instance and will be iterable just like regular QuerySet. Also all the records that was fetched from db will be a model instance. You can use it like:
users = User.objects.raw("SELECT * FROM users_user")
serializer = UserSerializer(users, many=True)
serializer.data
Don't forget to check out raw sql documentation.
Related
I'm new to django and django rest framework as a disclaimer.
I have a Model that contains metadata columns like last modified date and last modified user. This data should be available in the API for viewing but will be set automatically by the backend and hence must not be required for creation/update. As far as I understood I can create a dynamic serializer as shown in the docs.
However how can I use a dynamic serialize on a ViewSet? Or is that simply not possible?
If you want the last modified date and last modified user to be read only, you do not need to create a DynamicSerializer. All you need to do is to set the fields as read_only on the serializer.
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = (fields exposed to the API)
read_only_fields = ("last_modified_date", "last_modified_user")
After creating the serializer, it must be added to the ViewSet
class MyModelViewSet(viewsets.ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
I Develop a API [Django Rest Framework] for several purpose and ALL Data processed in JSON Format.
I have doubt about Serializer and it is must to used? and its Purpose?
My code:
class login(APIView):
def post(self, request):
jsondata = json.loads(request.body.decode('utf-8')).get('ls_json')
user_name = jsondata[0].get('username')
user_password = jsondata[0].get('password')
out_message = mCore.get_login(user_name, user_password)
return Response(out_message)
and url.py is :
urlpatterns = [
path('login/', view.login.as_view()),
]
and My Json Data Looks like :
{"ls_json":[{"username":"xy0003","password":"abcd"}]}
The above data is used to POST in api.
My Question is
1) Should i must use Serializer?
2) I deal In and OUT data as in JSON.
Serializers are used to do something with the data you send to the server against a Model. If you would like to do something with the data you are sending (In your example you could try to login or register an account) you will need to use serializers.
In this link you can find a lot of useful information on what are they used for and how to use them:
Django Serializers
I use Django REST Framework and I have a django model class like this:
class Venue(models.Model):
user=models.ForeignKey(User)
I would then want to serialize this:
from rest_framework import serializers
import models
class VenueSerializer(serializers.ModelSerializer):
class Meta:
model=models.Venue
fields=('id','user','is_current_user')
where is_current_user is a boolean value, somehow like this
def is_current_user(self):
return self.request.user==self.user
How can I do this? Do I have request somewhere in serializer? Or should I do this somewhere in the model?
Less convenient options are:
to send the current user id to the client in another way and compare there, but then I'd have to expose the user of each model to the client.
to iterate over the json after serialization
manually without the serializers create a json from a queryset
I would suggest using SerializerMethodField:
class VenueSerializer(serializers.ModelSerializer):
class Meta:
model=models.Venue
fields=('id','user','is_current_user')
def get_is_current_user(self, obj):
return self.context['request'].user == obj.user
In Django REST framework, what is involved in creating a flat, read-write serializer representation? The docs refer to a 'flat representation' (end of the section http://django-rest-framework.org/api-guide/serializers.html#dealing-with-nested-objects) but don't offer examples or anything beyond a suggestion to use a RelatedField subclass.
For instance, how to provide a flat representation of the User and UserProfile relationship, below?
# Model
class UserProfile(models.Model):
user = models.OneToOneField(User)
favourite_number = models.IntegerField()
# Serializer
class UserProfileSerializer(serializers.ModelSerializer):
email = serialisers.EmailField(source='user.email')
class Meta:
model = UserProfile
fields = ['id', 'favourite_number', 'email',]
The above UserProfileSerializer doesn't allow writing to the email field, but I hope it expresses the intention sufficiently well. So, how should a 'flat' read-write serializer be constructed to allow a writable email attribute on the UserProfileSerializer? Is it at all possible to do this when subclassing ModelSerializer?
Thanks.
Looking at the Django REST framework (DRF) source I settled on the view that a DRF serializer is strongly tied to an accompanying Model for unserializing purposes. Field's source param make this less so for serializing purposes.
With that in mind, and viewing serializers as encapsulating validation and save behaviour (in addition to their (un)serializing behaviour) I used two serializers: one for each of the User and UserProfile models:
class UserSerializer(serializer.ModelSerializer):
class Meta:
model = User
fields = ['email',]
class UserProfileSerializer(serializer.ModelSerializer):
email = serializers.EmailField(source='user.email')
class Meta:
model = UserProfile
fields = ['id', 'favourite_number', 'email',]
The source param on the EmailField handles the serialization case adequately (e.g. when servicing GET requests). For unserializing (e.g. when serivicing PUT requests) it is necessary to do a little work in the view, combining the validation and save behaviour of the two serializers:
class UserProfileRetrieveUpdate(generics.GenericAPIView):
def get(self, request, *args, **kwargs):
# Only UserProfileSerializer is required to serialize data since
# email is populated by the 'source' param on EmailField.
serializer = UserProfileSerializer(
instance=request.user.get_profile())
return Response(serializer.data)
def put(self, request, *args, **kwargs):
# Both UserSerializer and UserProfileSerializer are required
# in order to validate and save data on their associated models.
user_profile_serializer = UserProfileSerializer(
instance=request.user.get_profile(),
data=request.DATA)
user_serializer = UserSerializer(
instance=request.user,
data=request.DATA)
if user_profile_serializer.is_valid() and user_serializer.is_valid():
user_profile_serializer.save()
user_serializer.save()
return Response(
user_profile_serializer.data, status=status.HTTP_200_OK)
# Combine errors from both serializers.
errors = dict()
errors.update(user_profile_serializer.errors)
errors.update(user_serializer.errors)
return Response(errors, status=status.HTTP_400_BAD_REQUEST)
First: better handling of nested writes is on it's way.
Second: The Serializer Relations docs say of both PrimaryKeyRelatedField and SlugRelatedField that "By default this field is read-write..." — so if your email field was unique (is it?) it might be you could use the SlugRelatedField and it would just work — I've not tried this yet (however).
Third: Instead I've used a plain Field subclass that uses the source="*" technique to accept the whole object. From there I manually pull the related field in to_native and return that — this is read-only. In order to write I've checked request.DATA in post_save and updated the related object there — This isn't automatic but it works.
So, Fourth: Looking at what you've already got, my approach (above) amounts to marking your email field as read-only and then implementing post_save to check for an email value and perform the update accordingly.
Although this does not strictly answer the question - I think it will solve your need. The issue may be more in the split of two models to represent one entity than an issue with DRF.
Since Django 1.5, you can make a custom user, if all you want is some method and extra fields but apart from that you are happy with the Django user, then all you need to do is:
class MyUser(AbstractBaseUser):
favourite_number = models.IntegerField()
and in settings: AUTH_USER_MODEL = 'myapp.myuser'
(And of course a db-migration, which could be made quite simple by using db_table option to point to your existing user table and just add the new columns there).
After that, you have the common case which DRF excels at.
Imagine I have something like this:
def example = {
def temp = ConferenceUser.findAllByUser(User.get(session.user))
[temp: temp]
}
Explaining my problem:
Although dynamic finders are very easy to use and fast to learn, I must replace dynamic finders of my website for sql queries because it is a requirement. As I don't understand SQL that much, my main questions are:
a) I am using an SQLS database, with the drivers and datasource good configured and my website works as it is right now. If I want to replace the "findAllByUser" for an sql statement, should i do something like this:
def dataSource
...
def db = new Sql(dataSource)
def temp = db.rows("SELECT ... ")
b) And that will work? I mean, the temp object will be a list as it is if I use "findAllByUser", and do I need to open a connection to the database =?
With Grails you can use Dynamic Finders, Criteria Builders, Hibernate Query Language (HQL), or Groovy SQL.
To use Groovy SQL:
import groovy.sql.Sql
Request a reference to the datasource with def dataSource or def sessionFactory for transactions
Create an Sql object using def sql = new Sql(dataSource) or def sql = new Sql(sessionFactory.currentSession.connection())
Use Groovy SQL as required
Grails will manage the connection to the datasource automatically.
Sql.rows returns a list that can be passed to your view.
For example:
import groovy.sql.Sql
class MyController {
def dataSource
def example = {
def sql = new Sql(dataSource)
[ temp: sql.rows("SELECT . . .") ]
}
}
And within a transaction:
import groovy.sql.Sql
class MyController {
def sessionFactory
def example = {
def sql = new Sql(sessionFactory.currentSession.connection())
[ temp: sql.rows("SELECT . . .") ]
}
}
I recommend the book Grails Persistence with GORM and GSQL for a lot of great tips and techniques.
yes, with grails you can do both plain sql and hql queries. HQL is 'hibernate query language' and allows you to write sql-like statements, but use your domain classes and properties instead of the table names and column names. To do an hql query, do something like
def UserList = ConferenceUser.executeQuery('from ConferenceUser cu where cu.user = ?', [user]),
what you have here is a parameterized query -- executeQuery sees the ? in the hql string and substitutes the arguments in the array that is the second parameter to the method([user] in this case) for you.
See
http://grails.org/doc/latest/ref/Domain%20Classes/executeQuery.html
and you can see this on how to do sql queries with Grails
Sql query for insert in grails
Going Further / Tips
Use Spring beans
You can make the groovy.sql.Sql instance a Spring bean in your Grails application. In grails-app/conf/spring/resources.groovy define the Sql bean:
// File: grails-app/conf/spring/resources.groovy
beans = {
// Create Spring bean for Groovy SQL.
// groovySql is the name of the bean and can be used
// for injection.
sql(groovy.sql.Sql, ref('dataSource'))
}
Next inject the Sql instance in your your class.
package com.example
import groovy.sql.GroovyRowResult
class CarService {
// Reference to sql defined in resources.groovy.
def sql
List<GroovyRowResult> allCars(final String searchQuery) {
final String searchString = "%${searchQuery.toUpperCase()}%"
final String query = '''\
select id, make, model
from car
where ...
'''
// Use groovySql bean to execute the query.
final results = sql.rows(query, search: searchString)
results
}
}
Multiple Datasources
adminSql(groovy.sql.Sql, ref("dataSource_admin"))
userSql(groovy.sql.Sql, ref("dataSource_user"))
and inject the beans
def userSql
def adminSql
Into the services that need them.
or without injection
import groovy.sql.Sql
// ...
// inject the datasource bean
def dataSource_admin
// ...
// in a method
Sql sql = new Sql(dataSource_admin)
Early Grails Version
Looping through GORM result sets in early grails versions can cause needless queries in the middle of template loops. Using groovy SQL can help with this.