I'd like to extend django's auth.User, after reading this question,
this is my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User)
age = models.SmallIntegerField()
def create_user_profile(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
and I add this line in the bottom of my settings.py:
AUTH_PROFILE_MODULE = 'MYAPP.UserProfile'
The problem is, when I run python manage.py shell, and type:
from django.contrib.auth.models import User
user = User()
It works without problem! why doesn't it give an error that I didn't give a username/password?
When you run user = User(), all you are doing is creating a new User instance. It will not throw an error until you try to save it with user.save().
To simultaneously create and save a new model instance to the DB:
user = User.objects.create() # should throw an IntegrityError due to required (not NULL) fields not provided
Please ensure that UserProfile is inside of models.py in MYAPP and MYAPP is registered in INSTALLED_APPS. It seems like your signal doesn't work at all. If it won't help, try that in shell:
from django.contrib.auth.models import User
from MYAPP.models import UserProfile
user = User()
Thus you'll be sure that signal was properly registered.
The restrictions are mainly designed for form validation; there are very few restrictions (mainly those that may cause DB problems) that are enforced when you use the API.
You can easily create an empty user (a user with no username):
>>> from django.contrib.auth.models import User
>>> u = User()
>>> u.save()
>>> u
<User: >
>>> u.id
2
However, if you try to create two empty users you'll get an IntegrityError:
>>> u = User()
>>> u.save()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/base.py", line 460, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/base.py", line 553, in save_base
result = manager._insert(values, return_id=update_pk, using=using)
File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/manager.py", line 195, in _insert
return insert_query(self.model, values, **kwargs)
File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/query.py", line 1436, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 791, in execute_sql
cursor = super(SQLInsertCompiler, self).execute_sql(None)
File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 735, in execute_sql
cursor.execute(sql, params)
File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/backends/util.py", line 34, in execute
return self.cursor.execute(sql, params)
File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 234, in execute
return Database.Cursor.execute(self, query, params)
IntegrityError: column username is not unique
If you look at the model, you'll see there is a db-level restriction on the username field (unique=True):
`username = models.CharField(_('username'), max_length=30, unique=True...`
This is enforced at the API level, so you cannot have two users with the same username field.
Another example of this is the choices argument. This is used chiefly for presentation. If you have a field with choices=('M','Male'),('F','Female'); using the API you can insert any single character and it will happily accept it.
Options that are enforced at the database level (meaning, you can't "violate" them from the API) are:
unique
max_length
null (do not confuse with blank)
Related
I had a model Profile which was an extension to my User model which was the ForeignKey of my Post model, but I changed it to an AbstractUser and now if I try migrating or running and refreshing the page the server I get an error.
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
bio = models.TextField(max_length=500,null=True)
from django.db import models
from django.conf import settings
from django.urls import reverse
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=100)
content = models.TextField()
def get_absolute_url(self):
return reverse('post-details', kwargs={'pk': self.pk})
settings.py
INSTALLED_APPS = [
...
'posts',
'users',
]
AUTH_USER_MODEL = 'users.User'
error message after I try migrating
Apply all migrations: admin, auth, contenttypes, posts, sessions, users
Traceback (most recent call last):
File "/home/user/Projects/DNF/Project/manage.py", line 22, in <module>
main()
File "/home/user/Projects/DNF/Project/manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.10/dist-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python3.10/dist-packages/django/core/management/__init__.py", line 440, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python3.10/dist-packages/django/core/management/base.py", line 402, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/lib/python3.10/dist-packages/django/core/management/base.py", line 448, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python3.10/dist-packages/django/core/management/base.py", line 96, in wrapped
res = handle_func(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/django/core/management/commands/migrate.py", line 295, in handle
pre_migrate_apps = pre_migrate_state.apps
File "/usr/local/lib/python3.10/dist-packages/django/utils/functional.py", line 57, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/usr/local/lib/python3.10/dist-packages/django/db/migrations/state.py", line 566, in apps
return StateApps(self.real_apps, self.models)
File "/usr/local/lib/python3.10/dist-packages/django/db/migrations/state.py", line 637, in __init__
raise ValueError("\n".join(error.msg for error in errors))
ValueError: The field admin.LogEntry.user was declared with a lazy reference to 'users.user', but app 'users' doesn't provide model 'user'.
The field posts.Post.author was declared with a lazy reference to 'users.user', but app 'users' doesn't provide model 'user'.
The field users.Profile.user was declared with a lazy reference to 'users.user', but app 'users' doesn't provide model 'user'.
I easily solved it by deleting all the migration files in the migrations folder except the init.py file. And also delete db.sqlite3. Now run the following commands : python manage.py makemigrations and then python manage.py migrate. Now you'll have to create the super user once again, so for this just type the following commmand : python manage.py createsuperuser. Then it will prompt for username, email and password, so enter your credentials and all will continue to work properly once again I hope that this will be helpful.
try to directly reference the User model, not through settings
change the foreign key field to this:
author = models.ForeignKey("users.User", on_delete=models.CASCADE, null=True)
To have a reference to the User model, you should not do through settings directly instead you can use get_user_model() function. This function will return the currently active User model of project( the custom User model if one is specified, or User otherwise).
So change the foreign key field of your Post model like below:
from django.db import models
from django.conf import settings
from django.urls import reverse
from django.contrib.auth import get_user_model
User = get_user_model()
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
...
Reference: get_user_model() [Django-doc]
I'm trying to follow the tangowithdjango book and must add a slug to update the category table. However I'm getting an error after trying to migrate the databases.
http://www.tangowithdjango.com/book17/chapters/models_templates.html#creating-a-details-page
I didn't provide a default value for the slug, so Django asked me to provide one and as the book instructed I type in ''.
It's worth noticing that instead of using sqlite as in the original book I'm using mysql.
models.py
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
class Meta:
verbose_name_plural = "Categories"
def __unicode__(self):
return self.name
class Page(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=128)
url = models.URLField()
views = models.IntegerField(default=0)
def __unicode__(self):
return self.title
The command prompt
sudo python manage.py migrate
Operations to perform:
Apply all migrations: admin, rango, contenttypes, auth, sessions
Running migrations:
Applying rango.0003_category_slug...Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python2.7/dist-packages/django/core/management/commands/migrate.py", line 160, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 63, in migrate
self.apply_migration(migration, fake=fake)
File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 97, in apply_migration
migration.apply(project_state, schema_editor)
File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/migration.py", line 107, in apply
operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/operations/fields.py", line 37, in database_forwards
field,
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/schema.py", line 42, in add_field
super(DatabaseSchemaEditor, self).add_field(model, field)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/schema.py", line 411, in add_field
self.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/schema.py", line 98, in execute
cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 81, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/base.py", line 128, in execute
return self.cursor.execute(query, args)
File "/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 205, in execute
self.errorhandler(self, exc, value)
File "/usr/local/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
django.db.utils.IntegrityError: (1062, "Duplicate entry '' for key 'slug'")
Let's analyse it step by step:
You're adding slug field with unique = True, that means: each record must have different value, there can't be two records with same value in slug
You're creating migration: django asks you for default value for fields that exists already in database, so you provided '' (empty string) as that value.
Now django is trying to migrate your database. In database we have at least 2 records
First record is migrated, slug column is populated with empty string. That's good because no other record is having empty string in slug field
Second record is migrated, slug column is populated with empty string. That fails, because first record already have empty string in slug field. Exception is raised and migration is aborted.
That's why your migration fails. All you should do is to edit migration, copy migrations.AlterField operation twice, in first operation remove unique=True. Between that operations you should put migrations.RunPython operation and provide 2 parameters into that: generate_slugs and migrations.RunPython.noop.
Now you must create inside your migration function BEFORE migration class, name that function generate_slugs. Function should take 2 arguments: apps and schema_editor. In your function put at first line:
Category = apps.get_model('your_app_name', 'Category')
and now use Category.objects.all() to loop all your records and provide unique slug for each of them.
If you have more than one category in your table, then you cannot have unique=True and default='', because then you will have more than one category with slug=''. If your tutorial says to do this, then it's bad advice, although it might work in SQLite.
The correct approach to add a unique field to a model is:
Delete your current migration that isn't working.
Add the slug field, with unique=False. Create a new migration and run it.
Set a unique slug for every category. It sounds like the rango populate script might do this. Alternatively, you could write a migration to set the slugs, or even set them manually in the Django admin.
Change the slug field to unique=True. Create a new migration and run it.
If that's too difficult, then you could delete all your categories from your database except one. Then your current migration will run without having problems with the unique constraint. You can add the categories again afterwards.
You must have rows in your table already with empty slugs, which is a violation of the mysql unique constraint you created. You can update them manually by running manage.py dbshell to get to the mysql client, then updating the offending rows, e.g.
update table rango_category set slug = name where slug = '';
(assuming the rows with blank slugs have names). Or you can delete the rows with
delete from rango_category where slug = '';
After that, you should be able to run your migrations.
I'm learning to write an API using tastypie for a Django project. I have following code in models.py:
from django.db import models
from django.contrib.auth.models import User
class UserDeviceIds(models.Model):
user = models.ForeignKey(User)
device_id = models.CharField(max_length=15)
def __str__(self):
return self.device_id
class UserProfile(models.Model):
user = models.OneToOneField(User)
referral_code = models.CharField(max_length=8, unique=True)
def __str__(self):
return str(self.mal_rank)
And, I have following code in api.py:
class CreateUserProfileResource(ModelResource):
user = fields.ForeignKey('users.api.CreateUserResource', 'user', full=True)
class Meta:
list_allowed_methods = ['get','post']
always_return_data = True
authorization = Authorization()
authentication = Authentication()
validation = CreateUserProfileValidation()
resource_name = 'auth'
queryset = UserProfile.objects.all()
def hydrate(self, bundle):
bundle.data["user"]['username'] = bundle.data.get('country_code') + bundle.data.get("user")['username']
# Set a password automatically:
raw_password = ''.join(random.choice(string.ascii_lowercase) for i in range(8))
u = User(username='dummy')
u.set_password(raw_password)
bundle.data["user"]['password'] = u.password
return bundle
class CreateUserResource(ModelResource):
class Meta:
authorization = Authorization()
authentication = Authentication()
always_return_data = True
resource_name = 'user'
queryset = User.objects.all()
excludes = ['is_active', 'is_staff', 'is_superuser', 'date_joined', 'last_login']
When I send a POST request to http://127.0.0.1:8000/api/v1/auth (i.e:
curl -X POST -H "Content-Type: application/json" -d '{"user": {"email":"a#b.com","username":"abcdef"}, "referral_code":"abc123"}' http://127.0.0.1:8000/api/v1/auth
then a User and a UserProfile object is successfully created. But I would also like to create a UserDeviceIds object in the same endpoint. I have tried combination of different Tastypie Relationship Fields but I can't create a UserDeviceIds object. Can someone please elaborate on Tastypie relationship fields with some sample code to make me understand how the relationships work in Django?
For instance, I edited my CreateUserProfileResource in api.py and added the following line:
deviceid = fields.ForeignKey('users.api.CreateUserDeviceIdsResource', 'deviceid', full=True)
so that CreateUserProfileResource now looks like:
class CreateUserProfileResource(ModelResource):
user = fields.ForeignKey('users.api.CreateUserResource', 'user', full=True)
deviceid = fields.ForeignKey('users.api.CreateUserDeviceIdsResource', 'deviceid', full=True)
class Meta:
list_allowed_methods = ['get','post']
...
...
and added a new Resource for UserDeviceIds model:
class CreateUserDeviceIdsResource(ModelResource):
class Meta:
authorization = Authorization()
authentication = Authentication()
always_return_data = True
resource_name = 'deviceid'
queryset = UserDeviceIds.objects.all()
and when I try to send a POST request:
curl -X POST -H "Content-Type: application/json" -d '{"user": {"email":"a#b.com","username":"abcdef"}, "referral_code":"abc123", "deviceid": {"device_id": "abc"}}' http://127.0.0.1:8000/api/v1/auth
I get following error traceback:
{"error_message": "null value in column \"user_id\" violates not-null constraint
DETAIL: Failing row contains (2, abc, def, ghi, null).
", "traceback": "Traceback (most recent call last):
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
return self.cursor.execute(sql, params)
psycopg2.IntegrityError: null value in column \"user_id\" violates not-null constraint
DETAIL: Failing row contains (2, abc, def, ghi, null).
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 201, in wrapper
response = callback(request, *args, **kwargs)
File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 432, in dispatch_list
return self.dispatch('list', request, **kwargs)
File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 464, in dispatch
response = method(request, **kwargs)
File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 1340, in post_list
updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs))
File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2104, in obj_create
return self.save(bundle)
File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2247, in save
self.save_related(bundle)
File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2318, in save_related
related_resource.save(related_bundle)
File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2250, in save
bundle.obj.save()
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 589, in save
force_update=force_update, update_fields=update_fields)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 617, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 698, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 731, in _do_insert
using=using, raw=raw)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/manager.py\", line 92, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/query.py\", line 921, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/sql/compiler.py\", line 920, in execute_sql
cursor.execute(sql, params)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 81, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
return self.cursor.execute(sql, params)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/utils.py\", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File \"/vagrant/venv/lib/python3.4/site-packages/django/utils/six.py\", line 658, in reraise
raise value.with_traceback(tb)
File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: null value in column \"user_id\" violates not-null constraint
DETAIL: Failing row contains (2, abc, def, ghi, null).
"}
which I understand means that when it tried to save a UserDeviceIds object, it could not find data in bundle to put in the ForeignKey(User) field of UserDeviceIds model.
Can someone explain what needs to be done to make this code work?
Thanks!
You can't achieve it in current relation. The model resources are true reflection of models. For instance you could create this:
>>> UserProfile.objects.create(refferal_code='asdfasdf', user=User.objects.create_user(username='asdfasdf'))
or this:
>>> UserDeviceIds.objects.create(device_id='adfadf', user=User.objects.create_user(username='asdfasdfas'))
But not both in one instruction.
The REST API is great because it quite well feet Django ORM own interface.
So you can create object with children but not with other parents at the same time.
You have named your Resources with functional purpose creation that clearly suggest something is not right. Your Resource should be assign only to model.
In my own opinion REST API is great for working with, because it's clear, easy to understand for clients, easy rules, fast to build, easy to test. But doesn't feet really well sign-up with Django.
If you will have to break some RESTful rules don't try to redefine existing fully functioning Resources it can give a lot of pain. Instead Make some custom separated endpoint well described for this purpose.
I suggest to create custom view like endpoint handling json/xml whatever you support for sign-up. Hold it in separated app if you find better solution in future you will easily replace it. I suggest it because: 1. It's critical for you to create these 3 models in one call, it will break models if internet gets off. 2. Will be faster.
I doubt in existence of the ready apps solving the problem because sing-up is always bit unique for each website.
import json
from django.contrib.auth.models import User
from django.http import (HttpResponse, HttpResponseBadRequest,
HttpResponseNotAllowed)
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def signup(request):
"""
Description:
POST faldksfalskdfjalksdf
Headers:
sdfasdf
Attributes:
sadljfkasdlfksad
Responses:
asdf
"""
if request.method != 'POST':
return HttpResponseNotAllowed(permitted_methods=('POST',))
try:
data = json.loads(request.body)
except (AttributeError, ValueError):
return HttpResponseBadRequest(
json.dumps({'error': 'JSON format invalid',
'success': False}),
content_type='application/json')
if data.get('username', None) and data.get('device_id', None) and data.get('country', None):
# add more validation.
user = User.objects.create_user(username=data['username'])
UserProfile.objects.create(refferal_code='asdfasdf', user=user)
UserDeviceIds.objects.create(device_id='adfadf', user=user)
return HttpResponse(json.dumps({'success': True}),
content_type='application/json')
else:
return HttpResponseBadRequest(
json.dumps({'error': 'username, device_id or country attributes missing.',
'success': False}),
content_type='application/json')
I'm having troubles with adding new copy of existing model Clients, which looks like:
class Client(models.Model):
user = models.OneToOneField(User) # Extending default user model
organization = models.CharField(max_length=40)
def __unicode__(self):
return self.user.first_name + " " + self.user.last_name
Im entering shell and type this:
from django.contrib.auth.models import User
from mysiteApp.models import Client
user = User.objects.get(pk=2) # User with pk 2 exists
client = Client(user=user, organization="someorg") # copy creates succesfully
But then, im trying to save copy by
client.save()
And im getting this:
>>> client.save()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 537, in save
force_update=force_update, update_fields=update_fields)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 641, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 215, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1559, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 844, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 41, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py", line 389, in execute
six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py", line 387, in execute
return Database.Cursor.execute(self, query, params)
IntegrityError: mysiteApp_client.cID may not be NULL
The thing is that i HAD such field as cID in Client model before, wich really had NOT NULL, but now i dont
manage.py sql mysiteApp shows:
BEGIN;
CREATE TABLE "mysiteApp_client" (
"id" integer NOT NULL PRIMARY KEY,
"user_id" integer NOT NULL UNIQUE REFERENCES "auth_user" ("id"),
"organization" varchar(40) NOT NULL
)
;
manage.py syncdb changes nothing, what should i do?
Thanks.
Your database is still in the state as where the cID field is required. This is because syncdb does not alter already existing tables.
To overcome your problem you have three options:
a) delete the Client table (=lose your data) in your database and run syncdb again
b) manually modifying your database using a sql ALTER TABLE command
c) use a migration tool like South (introduction) to reflect the changes you did for models.py in your database. I would recommend to learn how to deal with South, as once you are in production you probably need such a migration tool.
I am trying to create a model for an existsing DB. Using the output of manage.py inspectdb, My models.py file looks like this:
from django.db import models
...some more stuff here...
class Scripts(models.Model):
run_site = models.ForeignKey(Sites, db_column='run_site')
script_name = models.CharField(max_length=120)
module_name = models.CharField(unique=True, max_length=120)
type = models.CharField(max_length=24)
cat_name = models.CharField(max_length=90)
owner = models.ForeignKey(QAPeople, db_column='owner')
only_server = models.CharField(max_length=120, blank=True)
guest = models.IntegerField()
registered = models.IntegerField()
super = models.IntegerField()
admin = models.IntegerField()
run_timing = models.CharField(max_length=27)
manual_owner = models.ForeignKey(QAPeople, db_column='manual_owner')
script_id = models.IntegerField(unique=True,)
version = models.IntegerField()
comment = models.ForeignKey('ScriptComments', null=True, blank=True)
class Meta:
db_table = u'scripts'
When I try to do Scripts.objects.all() I get
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Python26\lib\site-packages\django\db\models\query.py", line 68, in __repr__
data = list(self[:REPR_OUTPUT_SIZE + 1])
File "C:\Python26\lib\site-packages\django\db\models\query.py", line 83, in __len__
self._result_cache.extend(list(self._iter))
File "C:\Python26\lib\site-packages\django\db\models\query.py", line 269, in iterator
for row in compiler.results_iter():
File "C:\Python26\lib\site-packages\django\db\models\sql\compiler.py", line 672, in results_iter
for rows in self.execute_sql(MULTI):
File "C:\Python26\lib\site-packages\django\db\models\sql\compiler.py", line 727, in execute_sql
cursor.execute(sql, params)
File "C:\Python26\lib\site-packages\django\db\backends\util.py", line 15, in execute
return self.cursor.execute(sql, params)
File "C:\Python26\lib\site-packages\django\db\backends\mysql\base.py", line 86, in execute
return self.cursor.execute(query, args)
File "C:\Python26\lib\site-packages\MySQLdb\cursors.py", line 173, in execute
self.errorhandler(self, exc, value)
File "C:\Python26\lib\site-packages\MySQLdb\connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
OperationalError: (1054, "Unknown column 'scripts.id' in 'field list'")
Why does django think there should be a scripts.id column? How do I fix it without dropping the tables etc?
There is always by default an implicit id field as auto incrementing primary key on every model. See primary_key in the Django docs how to change that field to some other name, but there needs to be one primary key (also in your table).
Also you may not want to call one of your fields super, since it is shadowing Python's built-in super in the class body. Might give you a hard time finding a bug some day.
I'm not sure if you'r familiar with django-south?
It's a nice little tool that helps you migrate your data from one structure to another and also helps identify issues before commiting info to the table, causing less errors and debugging afterwards.