models . py :
class Equipe(models.Model):
NomEquipe = models.CharField(max_length=10,unique=True)
Description = models.CharField(max_length=10,unique=True)
class planning (models.Model):
datedebut= models.DateField
datefin=models.DateField
nbrH=models.TimeField
class Conseiller(models.Model):
Matricule = models.CharField(max_length=10,unique=True)
Nom = models.CharField(max_length=200)
Prenom = models.CharField(max_length=200)
Tel = models.CharField(max_length=200)
Mdp = models.CharField(max_length=200)
Email = models.EmailField(max_length=200)
File = models.CharField(max_length=200)
Preavis = models.BooleanField(default=False)
sup = models.CharField(max_length=200)
Equipe = models.ForeignKey(Equipe, on_delete=models.CASCADE)
planning = models.ForeignKey(planning , on_delete = models.CASCADE)
WHEN I try to execute Manage.py makemigrations a have the errors and i need to fix this
I think that you are new in Django. In first place, welcome :D
Second, and if you allow me, I give you some proposals before answer your ask.
Read Pep8 - Pep8 is a code styling by python. You code needs corrections in this way. The names of classes starts with Upper letter. The names of attributes, in lower case.
Be more specific in your ask. In your comment, you are more specific because you write your error...
Your error, is not an error :D. When you define an attribute, as Null=False (default, the attribute is not nulleable), you need specify default value if the table is already created. If you don't define default value, makemigrations command ask one. So, you have two options, define in model or in makemigrations. If your app is some for testing/dev/dummy and your db is clear, put on makemigrations a dummy value... When makemigrations give the two options, select 1 then, press 1 (in you case, attr planning is a foreign key, and is referenced with id integer number) if the attr is Charfield you can put '-', etc. If you have a prod app, you need see if your attribute can be 'nulleable' and set null=True, or see What is the best value in default=? param
Good luck!
The reason : you are trying to add a new field and your (model) database isn't empty ..
Solution : we need to add default value to records that already exists
Ex :
email = models.EmailField()
modify to
email = models.EmailField(default = None)
Related
Upon wanting to add some Markdown to a project, I've decided to install django-markupfield to serve this objective. The only thing is that I've installed my models and associated fields ahead of making this decision; now replacing a TextField with MarkupField.
When attempting to make a migration to adjust for this, the following is brought up:
You are trying to add a non-nullable field '_response_rendered' to answer 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 now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
What would be an appropriate default value to add to the fields that will be prompting for such? I have never been too sure of this question in general when it comes to using Django as well, so clarification would be appreciated.
https://github.com/jamesturk/django-markupfield
class Question(models.Model):
title = models.CharField(max_length=50)
body = MarkupField(
markup_type="markdown",
escape_html=True
)
dated = models.DateField(default=date.today)
user_account = models.ForeignKey(
'users.UserAccount',
on_delete=models.SET_NULL,
null=True, blank=True,
related_name="questions"
)
tags = models.ManyToManyField(Tag, related_name='questions')
objects = models.Manager()
dateranges = DateRangeQuerySet.as_manager()
status = QuestionStatusQuerySet.as_manager()
class Meta:
ordering = ['-dated']
default_manager_name = "objects"
def __str__(self):
return self.title
class Answer(models.Model):
question = models.ForeignKey(
Question,
on_delete=models.CASCADE,
related_name="answers"
)
response = MarkupField(
markup_type="markdown",
escape_html=True
)
dated = models.DateField(auto_now_add=True)
user_account = models.ForeignKey(
'users.UserAccount',
on_delete=models.SET_NULL,
null=True, blank=True,
related_name="answers"
)
You have to add default value.
In the background MarkupField create two fields (source link):
_rendered_field_name = lambda name: "_%s_rendered" % name # noqa
_markup_type_field_name = lambda name: "%s_markup_type" % name # noqa
class MarkupField(models.TextField):
...
def contribute_to_class(self, cls, name):
if self.rendered_field and not cls._meta.abstract:
...
cls.add_to_class(_markup_type_field_name(name), markup_type_field)
cls.add_to_class(_rendered_field_name(name), rendered_field)
super(MarkupField, self).contribute_to_class(cls, name)
setattr(cls, self.name, MarkupDescriptor(self))
The simple solution is provide default value at the time of migration:
So select choice 1 and enter default value. It will be add
default value only for the current migration, so your field is
non-nullable. Argument preserve_default(Django Docs) will be added.
Or provide default value in models.py:
class Question(models.Model):
...
body = MarkupField(
markup_type="markdown",
escape_html=True,
default="SOME VALUE"
)
...
class Answer(models.Model):
...
response = MarkupField(
markup_type="markdown",
escape_html=True,
default="SOME VALUE"
)
...
You can always remove default attribute and run makemigrations/migrate again.
THE BEST PRACTICE IS CREATE BACKUP BEFORE YOU RUN:
python manage.py makemigrations
python manage.py migrate
Try adding null = False to your field and migrate again. This usually works for me!
When I am trying to run python3 manage.py makemigrations it shows :
You are trying to add a non-nullable field 'topic_id' to journey_template 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 now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option:
enter code here
from django.db import models
class Topic_Table(models.Model):
topic_id=models.IntegerField(primary_key=True)
topic_name = models.CharField(max_length=100, blank=True)
weightage = models.CharField(max_length=15, blank=True)
grade = models.IntegerField( null=True)
subject = models.CharField(max_length=100, blank=True)
sequence = models.IntegerField(null=True)
month = models.CharField(max_length=15, blank=True)
class Journey_template(models.Model):
student_id = models.IntegerField(default=1)
topic_id = models.ForeignKey('Topic_Table',on_delete=models.CASCADE)
subtopic_id = models.IntegerField()
journey_template_key = models.IntegerField(primary_key=True)
How would I fix this?
You are adding the topic_id field on Journey_template model.
This model already has data on your database.
You have a few options:
1 - provide a default value (like entering the number 1)
2 - delete your database and start with a fresh migration
If you table already has data, adding a non-nullable column without any default will violate the non-null constraint. Django migration doesn't check the table for data, so it assumes there is some.
If your table has no rows, you can go ahead and give it any legal default value. The default does not change your model, it just gives Django a value it can fill in. Since there are no rows of data in the table, it will have no effect other than to make Django happy.
If you table has rows, then if you can think of a sensible value to populate the existing rows with, then use it. Your other option is to change the model by adding null=True to the field and Django will just put nulls in that field for existing rows. (Later, you can put your own values in to those fields with Django or other methods and change the field back to null=False if you like. You will get the same question when you migrate but the answer will have no effect if the fields are not null). null=False is the default for any field in your model.
I have the following models :
class Projects(models.Model):
id = models.IntegerField(primary_key=True, blank=True)
name = models.CharField(max_length=20, unique=True)
company = models.CharField(max_length=20, blank=True, null=True)
creation_date = models.DateField(auto_now_add=True, auto_now=False)
class Packages(models.Model):
id = models.IntegerField(primary_key=True, blank=True)
name = models.CharField(max_length=50)
extension = models.CharField(max_length=3)
gen_date = models.DateTimeField(auto_now_add=True, auto_now=False)
project = models.ForeignKey(Projects)
In my views, for the Homepage function, I'm trying to display the last package, AND the associated project. I don't understand how to retrieve the 'project' field (FK) :
try:
lastpackages = Packages.objects.reverse()[:1].get()
except Packages.DoesNotExist:
lastpackages = None
projectid = lastpackages.select_related('project_id')
project = Projects.objects.get(id=lastpackages.project)
return render(request, 'homepage.html', {'lastpackages': lastpackages,
'project': project})
In fact, I want to display the 'projectname' corresponding to the package retrieved by reverse. But the lines projectid and project are not correct. I hope it's enough clear..
Sorry to say but your code is a bit messy. You don't need to look up the Project separately, django ORM does it for you:
package = Package.objects.order_by('-id')[0]
project = package.project
package.project would give you the project associated with the package, no need to query using id.
Some advises here:
You don't need to define id, django will do it for you.
Don't use plural form in your model name, django will do it for you.
In view it's usually good exercise to use get_object_or_404 to get the object, it saves your try except block.
reverse() should be used along with order_by() statement. In your case it's easier to just use id to find the last entry, because in django id is auto incremented.
Try this:
lastpackage = Packages.objects.reverse()[0]
project = lastpackage.project
The first thing you need to keep in mind is that lastpackages is a Packages object, not a Queryset, so this line is wrong:
projectid = lastpackages.select_related('project_id')
It should return AttributeError: 'Packages' object has no attribute 'select_related'
About what you're asking, once you have a Packages object, you can get the corresponding project id like this:
lastpackages.project.pk
And the full Projects object, if needed:
lastpackages.project
I changed my model from this:
class DistList(models.Model):
creator = models.ForeignKey(User, related_name='creator')
created_date = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=200, unique=True)
description = models.TextField(blank=True, null=True)
company = models.ForeignKey(Company, blank=True, null=True)
To this:
class DistList(models.Model):
creator = models.ForeignKey(User, related_name='creator')
created_date = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=200, unique=True)
description = models.TextField(blank=True, null=True)
company = models.ForeignKey(Company)
The only change was turning the company FK relationship from not required to required.
When I run the migration I specify a one off value that corresponds to the pk of the first company.
./manage.py schemamigration distlist --auto
? The field 'DistList.company' does not have a default specified, yet is NOT NULL.
? Since you are making this field non-nullable, you MUST specify a default
? value to use for existing rows. Would you like to:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? Please select a choice: 2
? Please enter Python code for your one-off default value.
? The datetime module is available, so you can do e.g. datetime.date.today()
>>> 1
But when I run the migration I get an error because it has a pending trigger event?
./manage.py migrate distlist
Running migrations for distlist:
- Migrating forwards to 0005_auto__chg_field_distlist_company.
> distlist:0005_auto__chg_field_distlist_company
FATAL ERROR - The following SQL query failed: ALTER TABLE "distlist_distlist" ALTER COLUMN "company_id" SET NOT NULL;
The error was: cannot ALTER TABLE "distlist_distlist" because it has pending trigger events
I'm not doing anything that seems weird from my point of view so I don't understand this error at all. Can anyone offer insight? I can post the full stack trace if it'll help but I feel like theres something obvious about south and postgresql that perhaps I'm missing?
So I believe I've found the answer. I think postgresql doesn't like altering schemas and adding data at the same time. I first created a datamigration:
./manage.py datamigration distlist add_default_values_to_existing_companies
Then I added this to the forwards method:
def forwards(self, orm):
"Write your forwards methods here."
for distlist in orm['distlist.Distlist'].objects.all():
distlist.company = orm['userprofile.Company'].objects.get(id=1)
distlist.save()
Then I altered the model to remove the blank and null from company.
Then I ran the schema migration and chose to specify a one off for the value as 1 (as I did in the question).
Then I edited that migration file thusly:
def forwards(self, orm):
# Changing field 'DistList.company'
# db.alter_column(u'distlist_distlist', 'company_id', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['userprofile.Company']))
db.alter_column(u'distlist_distlist', 'company_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['userprofile.Company']))
I just commented out the generated line and removed the default=1 arg.
I don't know... maybe this isn't right but it seemed to work. Hopefully this will help someone.
I have a simple userprofile class in django such that
class Profile(models.Model):
user = models.OneToOneField(User,unique=True)
gender = models.IntegerField(blank=True, default=0, choices=UserGender.USER_GENDER,db_column='usr_gender')
education = models.IntegerField(blank=True, default=0, choices=UserEducation.USER_EDU,db_column='usr_education')
mail_preference = models.IntegerField(blank=True, default=1, choices=UserMailPreference.USER_MAIL_PREF,db_column='usr_mail_preference')
birthyear = models.IntegerField(blank=True, default=0,db_column='usr_birthyear')
createdate = models.DateTimeField(default=datetime.datetime.now)
updatedate = models.DateTimeField(default=datetime.datetime.now)
deletedate = models.DateTimeField(blank=True,null=True)
updatedBy = models.ForeignKey(User,unique=False,null=True, related_name='%(class)s_user_update')
deleteBy = models.ForeignKey(User,unique=False,null=True, related_name='%(class)s_user_delete')
activation_key = models.CharField(max_length=40)
key_expires = models.DateTimeField()
You can see that deletedBy and updatedBy are foreign key fields to user class. If I don't write related_name='%(class)s_user_update' it gives me error (I don't know why).
Although this works without any error, it doesn't push the user id's of deletedBy and updatedBy fields although I assign proper user to them.
Could give me any idea and explain the related_name='%(class)s_user_update' part ?
Thanks
'%(class)s_user_update' implies that it is a string awaiting formatting. You would normally see it in the context:
'%(foo)s other' % {'foo': 'BARGH'}
Which would become:
'BARGH other'
You can read more about python string formatting in the python docs. String Formatting Operations
I can't see how the code you have would ever work: perhaps you want:
class Profile(models.Model):
# other attributes here
updated_by = models.ForeignKey('auth.User', null=True, related_name='profile_user_update')
deleted_by = models.ForeignKey('auth.User', null=True, related_name='profile_user_deleted')
# other attributes here
If it does work, it is because django is doing some fancy magic behind the scenes, and replacing '%(class)s' by the class name of the current class.
Notes on the above:
The consistent use of *snake_case* for attributes. If you must use camelCase, then be consistent for all variables. Especially don't mix *snake_case*, camelCase and runwordstogethersoyoucanttellwhereonestartsandtheotherends.
Where you have two attributes that reference the same Foreign Key, you must tell the ORM which one is which for the reverse relation. It will default to 'profile_set' in this case for both, which will give you the validation error.
Use 'auth.User' instead of importing User into the models.py file. It is one less import you'll need to worry about, especially if you don't use the User class anywhere in your models.py file.
You can read more about the related_name stuff here:
https://docs.djangoproject.com/en/1.3/topics/db/queries/#following-relationships-backward