I have a simple model class:
class MyModel(models.Model):
place = models.CharField(max_length=25, verbose_name='Place')
name = models.CharField(max_length=25, verbose_name='Name')
And I'd like to ask you, is there a possibility to automatically set as default value for place field as number of records in table + 1
so for example if there will not be records in table the system automatically change the line to
place = models.CharField(max_length=25, verbose_name='Place', default='1')
Will be thankful for your help,
The default value can be a callable. i.e: you can call a method on the class to compute what you want the value to be.
So you could do:
class MyModel(models.Model):
def compute_default(self):
return <compute default, from query>
place = models.CharField(max_length=25, verbose_name='Place', default=compute_default)
Here's another reference: Result of database query as default value for Django model field?
Another option you might consider is to do this when the object is saved.
See: https://docs.djangoproject.com/en/2.0/ref/models/instances/#what-happens-when-you-save
You could use a signal, or override the .save() method on the object.
And I'd like to ask you, is there a possibility to automatically set as default value for place field as number of records in table + 1
For this part, you dont have to do anything. django does that automatically. It is called "id" field. So in your Model, first record will have a id of 1, second record will have id of 2 and so on.
For other default value, you can use default keyword.
class MyModel(models.Model):
place = models.CharField(max_length=25,verbose_name='Place',default="SomePlace")
name = models.CharField(max_length=25, verbose_name='Name')
Related
Models.py
class scenes(models.Model):
name = models.CharField('Event name', max_length=120)
record_date = models.DateTimeField('Event date')
Let's say I have recorded a scenes with name="world"
In views.py, how can I query the pk from the name field ?
from .models import scenes
scene = scenes.objects.get('what should I put here to get the pk associated with name World ?')
When I entered :
scene = scenes.objects.get(name='world').pk
I got an error :
UnboundLocalError: local variable 'scenes' referenced before assignment
The easy way to go with that would be to just:
# views.py
from .models import scenes
scene = scenes.objects.get(name="world")
scene_id = scene.pk # This contains the pk of the scene object
Django will try to fetch a unique object with "world" as a value for the name field. With your current code this has an issue:
Your name field is not unique so your DB may contain different scenes objects with the "world" value for the name field. This will lead to problems when calling get. To solve that you could add unique=True when defining the field:
# models.py
class scenes(models.Model):
name = models.CharField('Event name', max_length=120, unique=True)
record_date = models.DateTimeField('Event date')
This will ensure that your DB won't contain objects with the same name.
Note also that if there's no object with name value equal to "world" you'll get an error too. Depending on the context you are using this, you should consider get_object_or_404 or get_or_create
see this: The pk lookup shortcut.
The django documentation declares that primary keys have an equivalent, in this case it is pk. So if you declared a primary key in your model (let's say we called it code) you could access it as code or pk. This is useful both to apply filters (like the link above) or to obtain a specific attribute.
Now your question is how to obtain the associated primary key from the name of the event, I will show you below some solutions with consequences to how you declared the model.
A. Using scenes.objects.get():
If you use this method you must take into consideration two things:
That the search exists, it not exit, it raises Model.DoesNotExist exception.
That the search return only 1 object,it finds more than one object, it raises a Model.MultipleObjectsReturned exception:
please see the Queryset get() method
so if we ignore the second thing, the block of code is like this
# we have 1 object with the name `world`
try:
scene = scenes.objects.get(name="world")
scene_pk = scene.pk
except scenes.DoesNotExist:
print("The Scene does not Exists")
but the second you should use Queryset filter() method with other methods like first() or last()
So I recommend you re-make the Model like this:
class scenes(models.Model):
name = models.CharField('Event name',unique=True, max_length=120)
record_date = models.DateTimeField('Event date')
or using a SlugField like pk or unique field if you don't wanna change the id as primary key
class scenes(models.Model):
name = models.CharField('Event name', max_length=120)
slug = models.SlugField(unique=True)
record_date = models.DateTimeField('Event date')
the slugfield is ideal if you wish to use the name of the event in the URL.
I'm building a web crawler contain links blogs etc of x website ... , I have field called number_of_crawled_Links and I want to make the value of that filed is the number of rows in another model Where Links Stored i want the process to be automatically without making request any idea how to do that
You cannot do that in fields directly, but it's good idea to do that as a method.
class ModelA(models.Model):
some_field = models.TextField()
class ModelB(models.Model):
model_a = models.ForeignKey(ModelA, on_delete=models.CASCADE)
def get_some_field_value(self):
return self.model_a.some_field
Then ModelB can get dynamically the value of ModelA field some_field. You can do it with any type of values.
Model
class SlackPermission(models.Model):
#fields
class GithubPermission(models.Model):
#fields
class Employee(models.Model):
#fields
slack_permission = models.OneToOneField(SlackPermission, on_delete=models.CASCADE, related_name='Slack',default=SlackPermission.objects.get(pk=1))
github_permission = models.OneToOneField(GithubPermission, on_delete=models.CASCADE, related_name='Github',default=GithubPermission.objects.get(pk=1))
Error:
ValueError: Cannot serialize: <GithubPermission: GithubPermission object (1)>
There are some values Django cannot serialize into migration files.
I am creating API just to create Employee. Where there is not option of giving slackpermissions and githubpermissions. How do I give default value in there?
The problem is that the default is calculated immediately, and for migrations, it can not really serialize that.
That bing said, it is not very useful to do this anyway. You can just pass the primary key as default value. This is specified in the documentation on the default=… parameter [Django-doc]:
For fields like ForeignKey that map to model instances, defaults should be the value of the field they reference (pk unless to_field is set) instead of model instances.
So we can write this as:
class Employee(models.Model):
full_name = models.CharField(max_length=100)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
slack_permission = models.OneToOneField(
SlackPermission,
on_delete=models.CASCADE,
related_name='Slack',
default=1
)
github_permission = models.OneToOneField(
GithubPermission,
on_delete=models.CASCADE,
related_name='Github',
default=1
)
Note that you should ensure that there exists an object with that primary key. Therefore it might not be ideal to do that.
The issue here is that you are attempting to set a field value to an object instance. So your default value should be just 1 if you are certain of the pk.
Also, I am not sure the advantage of creating two separate models for these permission values. Seems like they can just be fields in your employee model. Seems like these permissions share identical fields as well which will allow you to flatten them a bit.
I created the following model to understand how to work with Django properties:
from django.db import models
class Person(models.Model):
_first_name = models.CharField(max_length=50, db_column='first_name')
#property
def first_name(self):
"""This is the getter. You can add logic too."""
return self._first_name
#first_name.setter
def first_name(self, fname):
self._first_name = fname
Why do I get the following error when I run the "makemigrations" command. I didn't have to specify default values for fields prior to Django 1.7. Does it have anything to do with my use of the property decorator?
Thanks.
You are trying to add a non-nullable field '_first_name' to person without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default...
2) Quit...
It is says that default models.CharField has the attribute blank=False witch means that it can't store an empty string value and it needs a default value in case it needs to store one, default="my default value" witch will be used if it has to store something equivalent to an empty string.
To fix this problem you can do the following
1)Allow empty strings values
You do this by specifying :
_first_name = models.CharField(max_length=50, db_column='first_name', blank=True)
2)Set a default value if it encounters and empty string
You give to him something to use instead of storing an empty string.
You do this by specifying :
_first_name = models.CharField(max_length=50, db_column='first_name', default="My default value")
By default we cannot store a empty string so we use blank=True to allow that.
Try this:
first_name = models.CharField(max_length=50, db_column='first_name',blank=False)
I have some models with relationships like this:
class Item(model.Model):
name = models.CharField()
class Group(models.Model):
item = models.ManyToManyField(Item)
class Serie(models.Model):
name = models.CharField()
chart = models.ForeignKey(Chart)
group = models.ForeignKey(Group)
class Chart(models.Model):
name = models.CharField()
I need to create a Chart object on the fly, without saving to the DB. But I can't do it because Django tries to use the objects primary keys when assigning the relationships.
I just want Group.add(Item()) to work without having to save the objects to the DB.
Is there any simple way around this?
Reviving here for the sake of future readers:
I've gotten around this use case by defining a private attribute that represents the relationship inside the classes and a property to inspect wether the object can be retrieved from the DB or resides in memory.
Here is a simple example:
class Parent(models.Model):
_children = []
name = models.CharField(max_length=100)
#property
def children(self):
if _children:
return self._children
else:
return self.children_set.all()
def set_virtual_children(self, value): # could use a setter for children
self._children = value # Expose _children to modification
def some_on_the_fly_operation(self):
print(','.join([c.name for c in self.children]))
class Children(models.Model):
parent = models.ForeignKey(Parent)
name = models.CharField(max_length=100)
This way, I can set the "virtual children" and use all the defined methods "on the fly"
EDIT: It seems that approach described here isn't enough for django to allow adding to the ManyToMany relationship.
Have you tried to add primary_key=True and unique=True to the name attribute of the Item model. Then doing Group.add(Item("item_name_here")) should work if you have the possibility to create the name on the fly.
I didn't test it, but I think your way failed because add() wants to use the primary-key which by default is the autoincrementing id that is assigned when it is saved to the database.