Introspecting Django queryset field lookups - python

I'm building a querybuilder in Django for something similar to an issues dashboard, which allows users to query and save dashboards for custom subsets of the issues in our database (e.g., all issues assigned to team A, created by client X, and created or updated in the current quarter). The frontend would allow the user to interact with the issues API to generate the list of issues they're looking for, and to save the filter criteria so they can visit the page and see an updated list of issues that match the filter criteria.
I'm thinking of saving the filter criteria as a dictionary in a JSONField, which I'd pass to the Model.objects.filter and the Q APIs.
I'd like to provide the Frontend a list of all eligible Field lookups (e.g., exact, iexact, contains, icontains, in, gt, etc.). Is there a class I can introspect to programmatically get a list of these lookups?
I read through the Field Lookup Docs tried looking through the Django source code, but couldn't find something similar to Model._meta.get_fields() for introspecting the fields on a model, as listed in the Model _meta API docs.

seems you are looking for this?
from django.db.models.fields import Field
f = Field()
f.get_lookups()
{'exact': <class 'django.db.models.lookups.Exact'>, 'iexact': <class 'django.db.models.lookups.IExact'>, 'gt': <class 'django.db.models.lookups.GreaterThan'>, 'gte': <class 'django.db.models.lookups.GreaterThanOrEqual'>, 'lt': <class 'django.db.models.lookups.LessThan'>, 'lte': <class 'django.db.models.lookups.LessThanOrEqual'>, 'in': <class 'django.db.models.lookups.In'>, 'contains': <class 'django.db.models.lookups.Contains'>, 'icontains': <class 'django.db.models.lookups.IContains'>, 'startswith': <class 'django.db.models.lookups.StartsWith'>, 'istartswith': <class 'django.db.models.lookups.IStartsWith'>, 'endswith': <class 'django.db.models.lookups.EndsWith'>, 'iendswith': <class 'django.db.models.lookups.IEndsWith'>, 'range': <class 'django.db.models.lookups.Range'>, 'isnull': <class 'django.db.models.lookups.IsNull'>, 'regex': <class 'django.db.models.lookups.Regex'>, 'iregex': <class 'django.db.models.lookups.IRegex'>}
Source code:
https://github.com/django/django/blob/bae053d497ba8a8de7e4f725973924bfb1885fd2/django/db/models/lookups.py#L361 - check the whole file.
There is also much older commit which might help, if you only want a static list: https://github.com/django/django/blob/d4e578d0f64971483ded49f9cae460ea174b5138/django/db/models/sql/constants.py#L11 but this one is not available for importing anymore.

Related

Django model Field default=None useful?

In my current project I'm working on we use default=None on model Fields, for models.CharField(default=''). Does this make any sense? I looked into the Django documentation, but couldn't find an answer. I searched the Django source code and for models Field the initial is set to default=NOT_PROVIDED and this is defined as
class NOT_PROVIDED:
pass
so I'm even more confused now. Running my tests in the Django project I had the feeling, that it does not really matter if I used default=None or default=''
Well, the difference depends on the use you are going to make of that specific data. For most cases, there is no difference, but you must have clear that '' and None are different Python data types:
>>> type('')
<class 'str'>
>>> type(None)
<class 'NoneType'>
>>>
So there would be a difference when the data type is transcendent in the use context of the data.
As documented
Avoid using null on string-based fields such as CharField and
TextField. If a string-based field has null=True, that means it has
two possible values for “no data”: NULL, and the empty string. In most
cases, it’s redundant to have two possible values for “no data;” the
Django convention is to use the empty string, not NULL. One exception
is when a CharField has both unique=True and blank=True set. In this
situation, null=True is required to avoid unique constraint violations
when saving multiple objects with blank values.

Unable to get repr for <class 'django.db.models.query.QuerySet'> when query'ing python 2 class

Django has following build in class:
#python_2_unicode_compatible
class ResetPasswordToken(models.Model):
I'm writing a test and want to check if there is a reset password token in db for a specific user. So I do:
token = ResetPasswordToken.objects.filter().all()
Hower python has problems with this:
Unable to get repr for <class 'django.db.models.query.QuerySet'>
I think this is because I am using python 3 and above the model there is a '#python_2_unicode_compatible'?
How can I do this correctly? Thanks
According to the definition of the decorator python_2_unicode_compatible for python3 it does nothing.
and error about queryset not about model. Please check on what python you are running your tests. and provide more description if possible (like lines you run in console)

Getting attributes of a model generated by swagger by using introspection in python

I have a model generated by swagger editor and would like to get its attributes by using introspection/reflection and also to find their types. I then would like to do something based on the type of the attributes.
The function that I have written to do this is;
def getting_attributes(Model1):
for name in dir(Model1):
attr = getattr(Model1,name)
if not callable(attr):
print(name,':',attr)
getting_attributes(test_model)
This works fine, but then I am unable to write if else statement to retrieve attr type.
The models' attributes that I get looks like this;
__dict__ : {'swagger_types': {'name': <class 'str'>, 'rdfs_label': <class 'str'>, 'rdfs_comment': <class 'str'>, 'has_a_b_c': typing.List[swagger_server.models.a_b_c.ABC], 'has_d_e_f': typing.List[swagger_server.models.d_e_f.DEF],.......}
'attribute_map': {'name': 'name', 'rdfs_label': 'rdfs.label',
'rdfs_comment': 'rdfs.comment', ....}
'_name': 'Test_model', '_rdfs_label': None, '_rdfs_comment': None,...}
When I try to find types of these attributes by doing print(name,":",type(attr)), I get most of them as <class 'NoneType'>. Any ideas on how to find if attribute is a type list, my model type or python type (i.e. string, integer, date...)?
p.s: I can't do attr.items() as it comes as string.

Django documentation reference

I am quite new to Django and I really don't get the documentation. For example in my code I query all available pages with Page.objects.public(). This gives me objects of type cms.models.pagemodel.Page. To use this in a template I need to know which methods I can use on this but I just cannot find the documentation and I cannot believe that I have to browse the Django source code to get to know the interface.
So does anyone know where I can find the available methods?
The Django model instance reference has some helpful stuff, but generally when working with model instances, we tend to access their data as attributes (which will be in the model definition) and we call the save method after updating these attributes.
The data types you'll get back from Django model instance attributes are all going to be Python objects, so it's usually more important to understand how to interact with those than to understand all the methods available on an instance.
To get to know a Django model, you should look at its definition. Here's an example:
class Page(models.model):
publication_date = models.DateTimeField(null=True)
name = models.CharField(max_length=255, blank=True)
For example, here, if you had a Page object with a publication_date, and that attribute was stored as a DateTimeField, then Django is going to give you a datetime object when you do:
>>> page = Page.objects.first()
>>> pubdate = page.publication_date
>>> type(pubdate)
<type 'datetime.datetime'>
Similarly, the name attribute is simply a Python string:
>>> page.name = "New page name"
>>> page.save()
# New page name is stored in the db and will be there when queried next.
Lastly, to output these things in a template, you would just refer to them in the same way:
Assuming you have a `page` variable here that is an instance...
Page Name is: {{ page.name }}
The Django book may be more helpful to familiarize yourself with interacting with Django models.

Get Python type of Django's model field?

How can I get corresponding Python type of a Django model's field class ?
from django.db import models
class MyModel(models.Model):
value = models.DecimalField()
type(MyModel._meta.get_field('value')) # <class 'django.db.models.fields.DecimalField'>
I'm looking how can I get corresponding python type for field's value - decimal.Decimal in this case.
Any idea ?
p.s. I've attempted to work around this with field's default attribute, but it probably won't work in all cases where field has no default value defined.
I don't think you can decide the actual python type programmatically there. Part of this is due to python's dynamic type. If you look at the doc for converting values to python objects, there is no hard predefined type for a field: you can write a custom field that returns object in different types depending on the database value. The doc of model fields specifies what Python type corresponds to each field type, so you can do this "statically".
But why would you need to know the Python types in advance in order to serialize them? The serialize modules are supposed to do this for you, just throw them the objects you need to serialize. Python is a dynamically typed language.
An ugly alternative is to check the field's repr():
if 'DecimalField' in repr(model._meta.get_field(fieldname)):
return decimal.Decimal
else:
...
However, you have to this for all types seperatly.

Categories