Sorting dictionary in django model using json field - python

I am trying to store a dictionary in my Django project as a model. The model is present but it wont update the values. any ideas?
model.py:
class MyModel(models.Model):
jsonM = JSONField()
Main.py:
myList = [1,2,3,4,5,6,7,8,9]
print("this is my model")
MyModel.objects.all().update(jsonM=myList)
When i do:
print(MyModel.objects.all())
print(type(MyModel.objects.all()))
I get the following:
<QuerySet []>
<class 'django.db.models.query.QuerySet'>

Try this:
newObject = MyModel(jsonM = mylist)
newObject.save()

Related

Querying a django model using a model name string input

Let's say i have the following django models:
class ModelB(models.Model):
title = models.CharField(max_length=20)
class ModelD(models.Model):
name = models.CharField(max_length=20)
In the django ORM, i am trying to read a string which will be the name of a model, and use it to query. Something like this:
>>b = 'ModelB'
>>b.objects.all()
This will obviously not work as it is a string. I have looked at ContentType but i am not sure how it will be helpful in my scenario. Any suggestions?
I also tried doing a get operation on Contentype like this:
>>> z = ContentType.objects.get(model='modelb')
>>> z
<ContentType: model b>
>>> z.__dict__
{'model': u'modelb', '_state': <django.db.models.base.ModelState object at 0x7f195346c150>, 'id': 14, 'app_label': u'testapp'}
>>>
But i did not know how to proceed further from here!
If you're using Django < 1.7, I think you can do this.
from django.db.models.loading import get_model
z = ContentType.objects.get(model='modelb')
ModelB = get_model(z.app_label, 'ModelB')
For django >= 1.7, you can
from django.apps import apps
z = ContentType.objects.get(model='modelb')
ModelB = apps.get_model(z.app_label, 'ModelB')
you can then use ModelB to query.

How to get properties of a model attribute?

Let's say that I have a class such as :
class MyClass(models.Model):
attributeA = models.CharField(max_length=100)
attributeB = models.IntegerField()
attributeC = models.CharField(max_length = 150, blank=True, nullable = True)
attributeD = models.ForeignKey('ModelB',related_name='FK_modelB')
attributeE = models.ManyToManyField('ModelC')
What I want to do is to get the properties of every attribute, not just the name that I got with :
my_instance._meta.get_all_field_name()
(which gave me a list of attributes names). No, what I want is, for every attribute, know what is his type (CharField,IntegerField, ForeignKey, ManyToManyField...), who's related if it's a ForeignKey / ManyToManyField and all the meta data such as max_length and so on.
The aim of it is to serialize a class into a XML and the representation in the XML will be different if it's a ManyToManyField, a ForeignKey or a simple value.
By the way, If anyone know a great class serializer to XML, it would help me a lot !
Thanks for your responses !
Django models _meta.fields is fields list that you can access to get field attributes:
>>> from django.contrib.auth.models import User
>>> u = User.objects.all()[0]
>>> u._meta.fields[1].__class__.__name__
'CharField'
>>> u._meta.fields[1].name
'username'
>>> u._meta.fields[1].max_length
30
>>> u._meta.fields[1].blank
False
# ...
You can get attributes of a specific field by using get_field()
MyClass._meta.get_field('attributeA').max_length

How to assign items inside a Model object with Django?

Is it possible to override values inside a Model?
I am getting 'MyModel' object does not support item assignment.
my_model = MyModel.objects.get(id=1)
print my_model.title
if my_model.is_changed:
my_model['title'] = 'something' # 'MyModel' object does not support item assignment
params = {
'my_model': my_model,
...
}
return render(request, 'template.html', params)
Models are objects, not dictionaries. Set attributes on them directly:
if my_model.is_changed:
my_model.title = 'something'
Or, if the attribute name is dynamic, use setattr:
attr_name = 'title' # in practice this would be more complex
if my_model.is_changed:
setattr(my_model, attr_name, 'something')
This changes the in-memory copy of the model, but makes no database changes - for that your attribute would have to be a field and you'd have the call the save method on my_model. You don't need to do that if you just want to change what the template receives in its context, but just for completeness's sake:
if my_model.is_changed:
my_model.title = 'something'
my_model.save()
Dictionaries are mutable, if you actually have a dictionary:
mydict = {'title': 'foo'}
# legal
mydict['title'] = 'something'
But not everything is a dictionary.
Yes, you can change values, but this is not how its done. Django Models are Python classes that have models to represent fields. For example a CharField is for holding a string in a database. Let me demonstrate (code from django docs):
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
As you can see above the Python class is a custom Django model. It is linked to a databse, and when you run manage.py syncdb, it will interact with your database to create the tables and columns that you need it to.
Now, in your case:
if my_model.is_changed:
my_model.title = "Something"
my_model.save()
my_model is an object. So, try this:
if my_model.is_changed:
my_model.title = 'something'
my_model.save()
I was using inlineformset_factory, what I had to do was:
Instead of using my_model.title = 'something',
I had to use my_model.instance.title = 'something'
views.py
...
if request.method == "POST":
formset = modelName2(request.POST, instance=modelName1)
if formset.is_valid():
if changeInstance == True:
models = formset
# change the title if changeInstance is True
index = 0
model = models[index]
model.instance.title = "something else"
model.save()
...

get class name for empty queryset in django

I have empty queryset of model Student
students = Students.objects.all()
If the above queryset is empty, then how can i get the model(class name)?
How can i get the model name for empty queryset?
EDIT:
How can i get the app name from the queryset?
>>> students = Students.objects.all()
# The queryset's model class:
>>> students.model
project.app.models.Student
# Name of the model class:
>>> students.model.__name__
'Student'
# Import path of the models module:
>>> students.model.__module__
'project.app.models'
# Django app name:
>>> students.model._meta.app_label
'app'
students.model
Querysets have a model attribute that can be used to retrieve the model they are associated with.
You can do:
students.model.__name__
>>> `Students`
To get the model name from queryset
queryset.__dict__['model'].__name__
If you want a model type which is a string:
queryset.model.__name__
You can check the type:
type(queryset.model.__name__)
>>> str
And if you want models.base.ModelBase type:
queryset.model._meta.model
You can check the type:
type(queryset.model._meta.model)
>>> django.db.models.base.ModelBase

Django Releationship between multiple fields

I just need a little help thinking through this, if someone could be so kind.
class object_a(models.Model):
foo = models.blah
bar = models.blah
class object_b(models.Model):
foop = models.blah
barp = models.blah
In another model I have a class that I want to have a single relationship with both fields. For example, in the admin I want a list of both object_a and object_b objects selectable in some sort of relationship.
I know a generic relationship of some sort can do this, I just can't quite get to the end of the though. all help is appreciated.
Thanks.
Use the contenttypes framework provided by Django:
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
class Other(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
Then you can create some of your main objects:
>>> from myapp.models import object_a, object_b, Other
>>> a = object_a()
>>> a.foo = 'test'
>>> a.bar = 'value'
>>> a.save()
>>> b = object_b()
>>> b.foop = 'random'
>>> b.barp = 'values'
>>> b.save()
And then save references to them in Other objects:
>>> o1 = Other()
>>> o1.content_object = a
>>> o1.save()
>>> o2 = Other()
>>> o2.content_object = b
>>> o2.save()
Now if we ask for all the Other objects and inspect them:
>>> all = Other.objects.all()
>>> all[0].content_object
<object_a: object_a object>
>>> all[0].content_object.foo
u'test'
>>> all[1].content_object
<object_b: object_b object>
>>> all[1].content_object.foop
u'random'
By looking at the fields on the Other object, we can see how Django stores the generic relations:
>>> all[0].content_type
<ContentType: object_a>
>>> all[0].object_id
1
When you run the syncdb command to install your models, Django creates a unique ContentType object for each model. When you use generic relations, you store a foreign key to this content type entry (identifying what type of object is at the other end of the relation), and the unique ID of the model instance. The generic.GenericForeignKey field is not stored in the database, but is a wrapper which takes the content type and object ID and retrieves the actual object for you.

Categories