Django automatically changes camel case - python-3.x

I am using models.IntegerChoices as Enum in Django, but it is saved in DB in a changed way.
class FruitsEnum(models.IntegerChoices):
Apple = 1
RedApple = 2
GreenApple = 3
LongBanana = 4
DragonFruit = 5
But it is saved in database like this : [('0','Apple'),('1','Redapple'),('2','Greenapple')...]
As you see the word 'apple' is not uppercase in two-word combinations. How Can I achive this :
[('0','Apple'),('1','RedApple'),('2','GreenApple')...]

Instead of passing integers, just pass a tuple consisting of the integer and the related name. Something like:
class FruitsEnum(models.IntegerChoices):
Apple = 1, 'Apple'
RedApple = 2, 'RedApple'
GreenApple = 3, 'GreenApple'
LongBanana = 4, 'LongBanana'
DragonFruit = 5, 'DragonFruit'
Alternatively, within your model, in the IntegerField where you're using this, you can replace FruitsEnum.choices with a tuple like:
[(1,'Apple'),(2,'RedApple'),(3,'GreenApple'),(4,'LongBanana'),(5,'DragonFruit')]
Note: Any differences you observe here are purely cosmetic and does not exist outside django (i.e within the database). You can open the database directly and see that only the integers are stored in the table.

Related

How to put single quotes with pyformat depending on input data type?

What I'm trying to do is to use pyformat with named parameters but respect the data types of input parameters.
"this is %(p1)s and this is %(p2)s" % values
I would like to format this as follows automatically without branching:
values = {p1 = 12, p2 = 'name'} produces this is 12 and this is 'name'
values = {p1 = 'name', p2 = 40} produces this is 'name' and this is 40
In other words, I would like to keep the quotes if they are present, otherwise substitute as it is. It doesn't need to be pyformat at all. Any library/framework/utility that does the job is also fine.

Filter django models by field and include data with null field

I have the dataset where i need to fetch some articles by companies, but also in same query i need to fetch data which have company = null.
Basically fetch company = 1 or company = null
I tried something like this but filter does not recognize None and just skip.
# example 1
Article.objects.filter(company__in=[1, None])
I tried something like this and this works, but i need something like example above, because i have framework for filtering which takes dict as custom filters, so i need key value pairs.
# example 2
Article.objects.filter(Q(company_id=1) | Q(company=None))
Is there any way i achive something like example 1 or some similar solutions?
EDIT:
If im stuck with example 2 is there any way i can combine those two, i have something like this in my framework.
Article.objects.filter(**custom_filter)
custom filter is dict, for example i have currently
custom_filter = {
'app': 1,
'company': 1
}
From what I can understand you have a custom_filter this does not have an in filter (At least with null values?). And you also have a list of ids you want and perhaps you may or may not want null values too. You can do something like below, to make such queries:
company_list = [1, 2, 3] # Don't put `None` here
nulls_needed = True # Change as per your need
custom_filter = {
'app': 1,
}
Article.objects.filter(
Q(company__isnull=nulls_needed) | Q(company__in=company_list), # positional args first
**custom_filter # keyword args later
)
Use __isnull as shown
Article.objects.filter(Q(company_id=1) | Q(company__isnull=True))

converting a python string to a variable

I have read almost every similar question but none of them seems to solve my current problem.
In my python code, I am importing a string from my bashrc and in the following, I am defining the same name as a variable to index my dictionary. Here is the simple example
obs = os.environ['obs']
>> obs = 'id_0123'
id_0123 = numpy.where(position1 == 456)
>> position1[id_0123] = 456
>> position2[id_0123] = 789
But of course, when I do positions[obs], it throws an error since it is a string rather than an index (numpy.int64). So I have tried to look for a solution to convert my string into a variable but all solution suggesting to either convert into a dictionary or something else and assign the string to an integer, But I can not do that since my string is dynamic and will constantly change. In the end, I am going to have about 50 variables and I need to check the current obs corresponding to which variable, so I could use it as indices to access the parameters.
Edit:
Position1 and Position 2 are just bumpy arrays, so depending on the output of os.environ (which is 'id_0123' in this particular case), they will print an array element. So I can not assign 'id_0123' another string or number since I am using that exact name as a variable.
The logic is that there are many different arrays, I want to use the output of os.environ as an input to access the element of these arrays.
If you wanted to use a dictionary instead, this would work.
obs = 'id_0123'
my_dict = {obs: 'Tester'}
print (my_dict [obs])
print (my_dict ['id_0123'])
You could use the fact that (almost) everything is a dictionary in Python to create storage container that you index with obs:
container = lambda:None
container.id_0123 = ...
...
print(positions[container.__dict__[obs]])
Alternatively, you can use globals() or locals() to achieve the desired behavior:
import numpy
import os
def environment_to_variable(environment_key='obs', variable_values=globals()):
# Get the name of the variable we want to reference from the bash environment
variable_name = os.environ[environment_key]
# Grab the variable value that matches the named variable from the environment. Variable you want to reference must be visible in the global namespace by default.
variable_value = variable_values[variable_name]
return variable_value
positions = [2, 3, 5, 7, 11, 13]
id_0123 = 2 # could use numpy.where here
id_0456 = 4
index = environment_to_variable(variable_values=locals())
print(positions[index])
If you place this in a file called a.py, you can observe the following:
$ obs="id_0123" python ./a.py
5
$ obs="id_0456" python ./a.py
11
This allows you to index the array differently at runtime, which is what it seems like your intention is.

Assigning specific dictionary values to variables

I have a series of dictionaries which each contain the same keys but their values are different i.e Age in dictionary 1 = 2, Age in dictionary 2 = 4 etc etc but they are broadly identical in structure.
what I would like to do is to randomly select one of these dictionaries and then assign specific values with the dictionary to variables. i.e python randomly chooses Dictionary 1 and then I then want to fill the dictAge variable with the age value from Dictionary 1.
import random
dictList = ['myDict', 'otherDict']
mydict = {
'age' : 10,
'other': "dummy data"
}
.
.
.
randomDict = random.choice(dictList)
dictAge = randomDict['age']
print(dictAge)
In the case of the code above what should happen is:
randomDict is assigned a random value from the distList variable (at the top). This sets which dictionary's values will be used going forward.
I next want the dictAge variable to then be assigned the age value from the selected dictionary. In this case (as mydict is was the only dictionary available) it should be assigned the age value of 10.
The error I am getting is:
TypeError: string indices must be integers
I know this is such a common error but my brain can't quite work out what the best solution is.
(Disclaimer: I haven't used python in ages so I know I am doing something really obviously silly but I can't quite work out what to do).
Right now, you are not actually using the definition of your dicts.
This is because dictList is comprised of strings: ['myDict', 'otherDict'].
So, when doing randomDict = random.choice(dictList), randomDict will either be the string 'myDict', or the string 'otherDict'.
Then you are doing randomDict['age'], which means you are trying to slice a string, with a string. As the error suggests, this can't be done and indices can only be ints.
What you want to do, is move the definition of the dictList to be after the definitions of your dicts, and include references to the dicts themselves, not strings. Something like:
mydict = {
'age' : 10,
'other': "dummy data"
}
.
.
.
dictList = [myDict, otherDict]
In the following piece of code:
dictAge = randomDict['age']
You are trying to index the name of dictionary variable (a string) returned by random.choice function.
To make it work you would need to do it using locals:
locals()[randomDict]['age']
or rather correct the dictList to contain the dictionaries instead of their names:
dictList = [myDict, otherDict]
In the latter case please note that myDict and otherDict should be declared before dictList.

How do I build a string of variable names?

I'm trying to build a string that contains all attributes of a class-object. The object name is jsonData and it has a few attributes, some of them being
jsonData.Serial,
jsonData.InstrumentSerial,
jsonData.Country
I'd like to build a string that has those attribute names in the format of this:
'Serial InstrumentSerial Country'
End goal is to define a schema for a Spark dataframe.
I'm open to alternatives, as long as I know order of the string/object because I need to map the schema to appropriate values.
You'll have to be careful about filtering out unwanted attributes, but try this:
' '.join([x for x in dir(jsonData) if '__' not in x])
That filters out all the "magic methods" like __init__ or __new__.
To include those, do
' '.join(dir(jsonData))
These take advantage of Python's dir method, which returns a list of all attributes of an object.
I don't quite understand why you want to group the attribute names in a single string.
You could simply have a list of attribute names as the order of a python list is persist.
attribute_names = [x for x in dir(jsonData) if '__' not in x]
From there you can create your dataframe. If you don't need to specify the SparkTypes, you can just to:
df = SparkContext.createDataFrame(data, schema = attribute_names)
You could also create a StructType and specify the types in your schema.
I guess that you are going to have a list of jsonData records that you want to consider as Rows.
Let's considered it as a list of objects, but the logic would still be the same.
You can do that as followed:
my_object_list = [
jsonDataClass(Serial = 1, InstrumentSerial = 'TDD', Country = 'France'),
jsonDataClass(Serial = 2, InstrumentSerial = 'TDI', Country = 'Suisse'),
jsonDataClass(Serial = 3, InstrumentSerial = 'TDD', Country = 'Grece')]
def build_record(obj, attr_names):
from operator import attrgetter
return attrgetter(*attr_names)(obj)
So the data attribute referred previously would be constructed as:
data = [build_record(x, attribute_names) for x in my_object_list]

Resources