I am currently working with one Django project.
I have the dictionary in it:
from models.py
class teltab(models.Model):
code=models.CharField(max_length=255)
telescope=models.CharField(max_length=255)
comment=models.CharField(max_length=255,blank=True)
and a form to add data to the dictionary:
class newtelescopesform(forms.ModelForm):
class Meta:
model=teltab
Usually I get a comment from the form and writes it to the dictionary:
from views.py
if len(request.GET['comment'])>0:
commentq=request.GET['comment']
tel_list.update(comment=commentq)
for item in tel_list:
item.save()
But now I need to append a new comment to an already existing cell in the resulting table.
Namely my table looks like this
and I want to get this
In fact either you define new comment model with a ForeignKey: teltab
class telTabModel(models.Model):
code=models.CharField(max_length=255)
telescope=models.CharField(max_length=255)
class CommentModel(models.Model):
teltab = models.ForeignKey('telTabModel', related_name='comments')
# ...
Or if you are using PostgreSQL you can use ArrayField as explained:
from django.contrib.postgres.fields import ArrayField
class telTabModel(models.Model):
code=models.CharField(max_length=255)
telescope=models.CharField(max_length=255)
comments = ArrayField(models.CharField(max_length=200), blank=True),
If you are not using PosgreSQL and you still want to use array you I will recommend Jsonfield
pip install jsonfield
from jsonfield import JSONField
class telTabModel(models.Model):
code=models.CharField(max_length=255)
telescope=models.CharField(max_length=255)
comments = JSONField(default=[])
I suppose u should change your model comment field type to TextField:
comment=models.TextField(blank=True)
Then just add "/n{new line}" to it
Edit: Dan's right, it s not a good idea there's opportunity to store lists in model if i'm not mistaken.
Related
I have a Django model in my python project with a meta class detailing it's indexes. I'm curious if there's a way to create the index using the nested path of the json object. In this case we know the structure of our json and I wanted to stick with a BTree or Hash index on the specific element.
If I were simply running this as raw sql, I'd expect to just do something like:
CREATE INDEX ON foster_data(root->'level_1'->'level_2'->>'name');
I was hoping I could do something like this in my model:
from django.db import models
from django.contrib.postgres import indexes
class ParentGuardians(Facilitators): # which extends models.Model
parent_identifier = models.IntegerField(db_column='p_id', default=None, blank=True,
null=True)
class Meta:
constraints = [
models.UniqueConstraint(fields=['table_id', name='UniqueConstraint for Parents')
]
indexes = [
models.Index(fields=['p_id', ]),
indexes.BTreeIndex(fields=[models.JSONField('{"root": {"level_1": {"level_2": "name"}}}'), ]
, name="jsonb_p_id_idx"),
]
or even:
...
indexes.BTreeIndex(fields=["root->'level_1'->'level_2'->>'name'", ]
...
But the named field fields only wants strings and only wants them to be the top level field defined in the model.
I'm aware of this questions: Indexing JSONField in Django PostgreSQL but it seems more of a hack and wanted the result generated from the codebase and makemigrations, not to manually edit it. Is this possible more recently?
Django 3.2 introduced native support for these indexes.
The question as asked presently doesn't seem to have the definition of the JSONField, but assuming it is something like
from django.db import models
class Facilitators(models.Model):
foster_data = models.JSONField()
To index a particular key, you combine an F expression with a JSONField path lookup on the model's Meta indexes option:
from django.contrib.postgres.fields import JSONField
class Facilitators(models.Model):
foster_data = models.JSONField()
class Meta:
indexes = [
models.Index(models.F("foster_data__root__level_1__level2__name"), name="foster_data__root__level_1__level2__name_idx"),
]
This will create a B-Tree index. If you are adding these to an existing model, be sure to makemigrations and migrate.
See this answer as well https://stackoverflow.com/a/74619523/
I need to use dictionary field on a Django Model.
for example, on a data
name = Kim, user_id = 12902938291, dictionary = {'yo' : 'drop', 'the': 'beat'}
I know about model serialization but it doesn't satisfy my requirement.
How to use dictionary field in Django?
Another clean and fast solution can be found here: https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.JSONField
For convenience I copied the simple instructions.
Usage
from django.db import models
class MyModel(models.Model):
json = JSONField()
So I have follwoing models:
class A(models.Model):
name = models.CharField()
age = models.SmallIntergerField()
class B(models.Model):
a = models.OneToOneField(A)
salary = model.IntergerField()
Now I want to create one rest end point for there two as they are one to one. So I want following as get
{
url: 'http://localhost/customs/1/',
name: 'abc',
age: 24,
salary: 10000
}
Similary, I want to create records and update as well. Please let me know how can I achieve this in django rest framework 3.
I just encountered the same problem, it would indeed be useful to make the response structure less tied to the underlying model structure. Here's my take :
Reading is easy
Serializer fields have a source parameter, which can take dotted names to traverse attributes.
class ABSerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = ['name', 'age', 'salary']
salary = serializer.IntegerField(source='b.salary') # this is your related_name
Writing is ... not officially supported
Validated data will show a nested structure, and the standard create and update methods will choke trying to assign a data dict to a OneToOneField.
The good news is that you can work around it by overriding create and update methods. Here's an example with update :
class ABSerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = ['name', 'age', 'salary']
related_fields = ['b']
salary = serializer.IntegerField(source='b.salary') # this is your related_name
def update(self, instance, validated_data):
# Handle related objects
for related_obj_name in self.Meta.related_fields:
# Validated data will show the nested structure
data = validated_data.pop(related_obj_name)
related_instance = getattr(instance, related_obj_name)
# Same as default update implementation
for attr_name, value in data.items():
setattr(related_instance, attr_name, value)
related_instance.save()
return super(ABSerializer,self).update(instance, validated_data)
Of course, this example is very simplistic, doesn't do any exception handling, and won't work with more deeply nested objects... but you get the idea.
Another option
You could also create a read-write flavor of SerializerMethodField, which would consider both a getter and a setter, however that would probably end up being far more verbose in the end.
Hope that helps !
I know this is an old post but I came across this and after some research and reading through the Django Rest Framework documentation
So a quick search I found that you could use the related_name parameter for reverse relationships as stated here:
reverse relationships are not automatically included by the
ModelSerializer and HyperlinkedModelSerializer classes. To include
a reverse relationship, you must explicitly add it to the fields list.
For example:
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ['tracks', ...]
You'll normally want to ensure that you've set an appropriate
related_name argument on the relationship, that you can use as the
field name.
For example:
class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks',
on_delete=models.CASCADE)
...
If you have not set a related name for the reverse relationship,
you'll need to use the automatically generated related name in the
fields argument.
For example:
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ['track_set', ...]
Also, see the Django documentation on reverse
relationships
for more details.
I would like a bigger auth_user table, including 2-3 extra fields.
The thing is that the code below is creating a new one, exactly the same as the auth_user one with the extra fields but it is not replacing it.
settings.py
AUTH_PROFILE_MODULE = "myaccount.MyUser"
models.py
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
gender = models.DateField()
location = models.CharField(max_length=30)
birthday = models.CharField(max_length=30)
Instead of creating a new table called myaccount_MyUser. How can I replace the current auth_user table instead of creating a new table?
I believe that this one can help you :
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-user
One hackish way that I didn't try and don't recommend would be to specify the table name in the model with:
class MyUser(AbstractUser):
class Meta:
db_table = auth_user
What I recommend is going along with the new table and migrating the data from the old one using south datamigration. Here is a detailed answer on how to do that:
Migrating existing auth.User data to new Django 1.5 custom user model?
I think that you have to
import first django.contrib.auth.models
import AbstractUser
in your models.py before to get a way to extend with AbstractUser. it should work with that
I've defined a models.py with a "FirstClass" which contains a ForeignKey relathionship to "SecondClass". The relathionship can't be Null.
The SecondClass is very expansive (90.000 records), and when i display the FirstClass html form, it requires too many time generating the "select box" field.
Therefore, when I let user update the object (I use create_update.update_object generic view), i don't want to display and update the value of the foreignkey field, but i don't know how to do this...
Create a ModelForm and pass it into the view, according to the docs.
Since the foreign key should always exist upon creation, it's safe to ignore it in the update.
class MyModelForm(forms.ModelForm):
class Meta:
model = FirstClass
exclude = ('SecondClass',)
# urls.py
(r'^foo/(?P<object_id>\d+)/$','django.views.generic.create_update.update_object',
{'form_class': MyModelForm})