Django - how can i call a model as a string? - python

I'm building a DRF api endpoint that should render some json data from my database. In my view, the name of the model to query to render the data is not fixed, it depends on what query does the user perform.
So i have this:
collection = 'MY_MODEL'
queryset = collection.objects.filter(**filters)
But this will give the following error:
'str' object has no attribute 'objects'
This will work instead: queryset = MY_MODEL.objects.filter(**filters)
Is there any way to get around this?

Django actually has a method to do this:
from django.utils.module_loading import import_string
ModelClass = import_string('yourapp.models.YOUR_MODEL')
queryset = ModelClass.objects.filter(**filters)
Note that you have to provide the full path of your model.
The docs: https://docs.djangoproject.com/en/3.1/ref/utils/#django.utils.module_loading.import_string
If you only have a few models you need to support however I would actually advise to just use a dictionary that you maintain yourself:
MODEL_MAPPING = {
"model_a": MyModelAClass,
"model_b": MyModelBClass,
}
user_input = "model_b"
ModelClass = MODEL_MAPPING.get(user_input)
if ModelClass is not None:
queryset = ModelClass.objects.filter(**filters)

Related

How to receive get parameter in viewset in django restframe work?

For the part of developing an API using restframe work and DJango, I need to receive few parameters through get method in 'list' function of my Viewset. In client side they are sending data as query prams, I somehow managed to get the data using 'request.query_params.get()' but received data is text format instead of bool, I had to convert this to boolean . see the code how I did this
if 'status' in (request.query_params):
"""receiving input argument is string need to convert that to boolean for further processing"""
input_status=(request.query_params.get('status', None)=='true')
is there any better way to getting data without losing datatype. is it possible to receive 'bool' or 'int' values directly in get parameter?
My model and view set classes are given below
class ModuleType(models.Model):
"""
This module type class used to represent each module of the application. It is inherited from
django content type which holds the complete model informations
"""
#this active field is true this module will be active on our user controller
content_type = models.OneToOneField(
ContentType,
on_delete=models.CASCADE,
related_name='status',
null=True
)
active=models.BooleanField(default=False)
class Meta:
db_table = 'module_types'
My Viewset
class ContentTypeViewSet(viewsets.ModelViewSet):
"""
This api deals all operations related with module management
You will have `list`, `create`, `retrieve`,
update` and `destroy` actions.
Additionally we also provide an action to update status.
"""
queryset = ContentType.objects.all()
serializer_class = ContentTypeSerializer
permission_classes = [permissions.AllowAny]
"""
Over ride list method to list values
"""
def list(self, request):
status='Sucess'
message='details of all modules included'
print(request)
try:
if 'status' in (request.query_params):
#input argument is striing need to convert that to boolean
input_status=(request.query_params.get('status', None)=='true')
validated_value= self.validate_input_params({'status':input_status})
if (validated_value==1):
all_modules = ContentType.objects.filter(status__active=input_status)
message='All value set status as '+str(input_status)
else:
message='Failed to validate all input values'
status='fail'
return Response({"status":status,"data":[],"message":message})
else:
all_modules=ContentType.objects.all()
serializer = self.get_serializer(
all_modules,
many=True
)
return Response({"status":status,"data":serializer.data,'message':message})
except:
message='unknown exception'
status='Fail'
return Response({"status":status,"data":[],"message":message})
Your view will read query params as string.
I suggest you use query_params = dict(request.GET.items())
That way you can parse parameters easier by using dict.

How to obtain content_type from a Django Model Class?

I am trying to obtain the ContentType for a django models.Model. Not trying to get the model from a ContentType, which is all I can find in the docs. For example:
model_name = 'FooBar'
MyModel = apps.get_model('app_xyz', model_name)
MyModel
<class 'apps.app_xyz.models.FooBar'>
How do I get the ContentType of MyModel? The only thing I can figure out to do is set the model_name string to lower and directly query ContentTypes:
ct = ContentType.objects.get(model=model_name.lower())
That seems really fragile, and using lower() has a code smell I don't like. I've looked through FooBar's methods, _methods, and __methods to no avail. Thanks!
from django.contrib.auth.models import User
cc = ContentType.objects.get_for_model(User)
docs

Flask Sqlalchemy add multiple row

I am using flask-restful this is
My class I want to insert
class OrderHistoryResource(Resource):
model = OrderHistoryModel
schema = OrderHistorySchema
order = OrderModel
product = ProductModel
def post(self):
value = req.get_json()
data = cls.schema(many=True).load(value)
data.insert()
In my model
def insert(self):
db.session.add(self)
db.session.commit()
schema
from config.ma import ma
from model.orderhistory import OrderHistoryModel
class OrderHistorySchema(ma.ModelSchema):
class Meta:
model = OrderHistoryModel
include_fk = True
Example Data I want to insert
[
{
"quantity":99,
"flaskSaleStatus":true,
"orderId":"ORDER_64a79028d1704406b6bb83b84ad8c02a_1568776516",
"proId":"PROD_9_1568779885_64a79028d1704406b6bb83b84ad8c02a"
},
{
"quantity":89,
"flaskSaleStatus":true,
"orderId":"ORDER_64a79028d1704406b6bb83b84ad8c02a_1568776516",
"proId":"PROD_9_1568779885_64a79028d1704406b6bb83b84ad8c02a"
}
]
this is what i got after insert method has started
TypeError: insert() takes exactly 2 arguments (0 given)
or there is another way to do this action?
Edited - released marshmallow-sqlalchemy loads directly to instance
You need to loop through the OrderModel instances in your list.
You can then use add_all to add the OrderModel objects to the session, then bulk update - see the docs
Should be something like:
db.session.add_all(data)
db.session.commit()
See this post for brief discussion on why add_all is best when you have complex ORM relationships.
Also - not sure you need to have all your models/schemas as class variables, it's fine to have them imported (or just present in the same file, as long as they're declared before the resource class).
You are calling insert on list cause data is list of model OrderHistoryModel instances.
Also post method doesn't need to be classmethod and you probably had an error there as well.
Since data is list of model instances you can use db.session.add_all method to add them to session in bulk.
def post(self):
value = req.get_json()
data = self.schema(many=True).load(value)
db.session.add_all(data)
db.session.commit()

Check if record exists in Django Rest Framework API LIST/DATABASE

I want to create a viewset/apiview with a path like this: list/<slug:entry>/ that once I provide the entry it will check if that entry exists in the database.
*Note: on list/ I have a path to a ViewSet. I wonder if I could change the id with the specific field that I want to check, so I could see if the entry exists or not, but I want to keep the id as it is, so
I tried:
class CheckCouponAPIView(APIView):
def get(self, request, format=None):
try:
Coupon.objects.get(coupon=self.kwargs.get('coupon'))
except Coupon.DoesNotExist:
return Response(data={'message': False})
else:
return Response(data={'message': True})
But I got an error: get() got an unexpected keyword argument 'coupon'.
Here's the path: path('check/<slug:coupon>/', CheckCouponAPIView.as_view()),
Is there any good practice that I could apply in my situation?
What about trying something like this,
class CheckCouponAPIView(viewsets.ModelViewSet):
# other fields
lookup_field = 'slug'
From the official DRF Doc,
lookup_field - The model field that should be used to for performing
object lookup of individual model instances. Defaults to pk

TypeError django context using custom class

I am new to python and django, and I am trying to pass a class to my RequestContext in a template. So I have this code:
context = RequestContext(request, {
'test' : myClass,
})
And myClass is an instance of this:
class ajax_user_session():
user_model = None
user_settings = None
time_login = datetime.datetime.now()
Both user_model and user_settings are classes derived from django's models.Model (assigned before creating and using the context class). I get the following error:
TypeError at /settings
<playground.ajax_processing.ajax_user_session instance at 0x263fab8> is not JSON serializable
Does somebody know how to solve this, please? I can assign "normal" variables like strings, integers, but I don't want to add several things to the dictionary, I just want to use one big class.
Thank you.
Try this:
from django.forms.models import model_to_dict
context = RequestContext(request, {
'test' : model_to_dict(myClass),
})
Sometime model_to_dict has problems with datetime, so you may need to exclude that field with model_to_dict(myClass, exclude=time_login) and then set that manually.

Categories

Resources