Using OneToOneField in Django - python

I'm realized some models in application:
from django.db import models
class Commentary(models.Model):
user_id = models.ForeignKey(User)
created_date = models.DateField()
comment = models.TextField()
class Role(models.Model):
role_name = models.CharField(max_length=25)
class User(models.Model):
login = models.CharField(max_length=50)
password = models.CharField(max_length=50)
address = models.CharField(max_length=255)
phone = models.CharField(max_length=25)
postcode = models.CharField(max_length=25)
email = models.EmailField()
role_id = models.OneToOneField(Role)
After that typed in console "python manage.py makemigration mainws" for making migrations in my database, however, taken stacktrace with error. If looking in django documentation for one-to-one example, we can see the similarity with him, but without option primary_key=True. How can I fix this or maybe better using ForeignKey with unique=True for this issue, or something other?
Stacktrace:
=> python manage.py makemigration mainws
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/Users/savicvalera/code/lab8/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/Users/savicvalera/code/lab8/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute
django.setup()
File "/Users/savicvalera/code/lab8/lib/python2.7/site-packages/django/__init__.py", line 21, in setup
apps.populate(settings.INSTALLED_APPS)
File "/Users/savicvalera/code/lab8/lib/python2.7/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models(all_models)
File "/Users/savicvalera/code/lab8/lib/python2.7/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "/usr/local/Cellar/python/2.7.8_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/Users/savicvalera/code/lab8/website/mainws/models/__init__.py", line 1, in <module>
from . import Commentary, MailList, Product, Provider, Rate, Review, Role, Sale, ShoppingCart, Status, Supplies, User
File "/Users/savicvalera/code/lab8/website/mainws/models/Commentary.py", line 11, in <module>
from . import Product, User
File "/Users/savicvalera/code/lab8/website/mainws/models/User.py", line 14, in <module>
class User(models.Model):
File "/Users/savicvalera/code/lab8/website/mainws/models/User.py", line 21, in User
role_id = models.OneToOneField(Role,to_field='id')
File "/Users/savicvalera/code/lab8/lib/python2.7/site-packages/django/db/models/fields/related.py", line 1799, in __init__
super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs)
File "/Users/savicvalera/code/lab8/lib/python2.7/site-packages/django/db/models/fields/related.py", line 1612, in __init__
assert isinstance(to, six.string_types), "%s(%r) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string %r" % (self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
AssertionError: OneToOneField(<module 'mainws.models.Role' from '/Users/savicvalera/code/lab8/website/mainws/models/Role.pyc'>) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string u'self'

If I understand your code organization correctly, the problem is in your imports. When you say
from . import Role
you're importing Role.py into a module object named Role. Inside that module (I assume) is your Role model class. So what you really want is:
from .Role import Role
Or:
from . import Role
...
role_id = models.OneToOneField(Role.Role)

You should define an app_label in your meta class
class Foo(models.Model):
class Meta:
app_label = 'mainws'

Related

Django Error (Attribute): 'CharField' object has no attribute 'is_related'

I am trying to make a description to every user, in my new project. But i get an error when i try to makemigrations. I do not know how to fix it.
I have tried different things but nothing worked, my coding is maybe very bad, but i am also new to python and django.
The Error:
C:\Users\bruger\Dropbox\min-login-web\web_login>python manage.py makemigrations
Traceback (most recent call last):
File "manage.py", line 15, in <module>
execute_from_command_line(sys.argv)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line
utility.execute()
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\base.py", line 316, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\base.py", line 353, in execute
output = self.handle(*args, **options)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\base.py", line 83, in wrapped
res = handle_func(*args, **kwargs)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\commands\makemigrations.py", line 143, in handle
loader.project_state(),
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\loader.py", line 322, in project_state
return self.graph.make_state(nodes=nodes, at_end=at_end, real_apps=list(self.unmigrated_apps))
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\graph.py", line 378, in make_state
project_state = self.nodes[node].mutate_state(project_state, preserve=False)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\migration.py", line 87, in mutate_state
operation.state_forwards(self.app_label, new_state)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\operations\models.py", line 85, in state_forwards
list(self.managers),
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\state.py", line 377, in __init__
if field.is_relation and hasattr(field.related_model, '_meta'):
AttributeError: 'CharField' object has no attribute 'is_relation'
My Models file:
from django import forms
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from PIL import Image
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
def save(self):
super().save()
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
class Desc(models.Model):
description = forms.CharField(widget = forms.Textarea, max_length = 250, required=False)
def __str__(self):
return f'{self.user.username} Desc'
I Hope somebody can help me, because this is really getting on my nerves.
You mixed forms and models. A model does not specify a (HTML) form, it specifies how the database should store data, so you need to use a models.CharField:
class Desc(models.Model):
description = models.CharField(max_length=250)
Such CharField has no widget assigned to it, this is something you should handle at the form level.
You probably will need to make migrations, since up to this point, there was no description field in your Desc model.
I agree to some extent that it is confusing that the forms have frequently a field with the same name (well those typically are the default form fields for the model field with the same name). The idea is however that model fields specify the columns in a database, whereas form fields specify text boxes, check boxes, etc. in a (HTML) form.

"auth_user does not exist" when doing unit testing in django

I've been trying to solve this error for a week now and I can't seem to figure out how to fix this error. No one else who is using this repository is having the same problem as I am (I am up to date with the origin), so it has to be some sort of local issue, but I can't figure out what it would be.
This happens everytime I try to run the django unit tests that we have written. There are no problems when I runserver or when I do migrations, only when testing:
python manage.py test
_______ERROR MESSAGE:_________
Liams-MBP:GrammieGram Liam2$ python manage.py test grams
Creating test database for alias 'default'...
Traceback (most recent call last):
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: relation "auth_user" does not exist
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/__init__.py", line 364, in execute_from_command_line
utility.execute()
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/__init__.py", line 356, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/commands/test.py", line 29, in run_from_argv
super(Command, self).run_from_argv(argv)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/commands/test.py", line 62, in handle
failures = test_runner.run_tests(test_labels)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/test/runner.py", line 601, in run_tests
old_config = self.setup_databases()
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/test/runner.py", line 546, in setup_databases
self.parallel, **kwargs
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/test/utils.py", line 187, in setup_databases
serialize=connection.settings_dict.get('TEST', {}).get('SERIALIZE', True),
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/db/backends/base/creation.py", line 69, in create_test_db
run_syncdb=True,
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/__init__.py", line 131, in call_command
return command.execute(*args, **defaults)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/commands/migrate.py", line 173, in handle
self.sync_apps(connection, executor.loader.unmigrated_apps)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/core/management/commands/migrate.py", line 311, in sync_apps
self.stdout.write(" Running deferred SQL...\n")
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 93, in __exit__
self.execute(sql)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 120, in execute
cursor.execute(sql, params)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/Users/Liam2/anaconda3/lib/python3.6/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "auth_user" does not exist
My grams/models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
import datetime
import uuid
from django.contrib.postgres.fields import ArrayField
from django.db.models.signals import post_save
from django.dispatch import receiver
"""
#brief A class that describes a user profile.
#field user - the username of the user
#field usertype - the type of user profile (sender/receiver)
#filed contacts - the user's contact book, list of people they can contact
#field admins - and a list of admins, list of users who have admin
privileges over this Profile object
"""
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
usertype = models.CharField(max_length=30, default="sender")
contacts = ArrayField(models.CharField(max_length=150, default="default"), default=[])
admins = ArrayField(models.CharField(max_length=150, default="default"), default=[])
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
"""
#brief Describes a gram message that a sender type Profile is
able to send to a receiver type Profile.
#field send_username - the username of the sender profile
#field recp_username - the username of the receiver profile
#field sent_time - the time at which the Gram object was sent
#field display_until - the amount of time the Gram object will be visible
"""
class Gram(models.Model):
message = models.CharField(max_length=240)
send_username = models.CharField(max_length=150, default="default")
recp_username = models.CharField(max_length=150, default="default")
sent_time = models.DateTimeField(null=True)
display_until = models.DateTimeField(null=True)
def __str__(self):
return self.message
#function checks if another user can be added to the list of contacts
#active_user_type - logged in user; new_contact - the contact to be added
def validated_contact_add(active_user_type,new_contact):
#check if the contact exists in the list of users
if User.objects.filter(username=new_contact).exists():
#check if the type of the logged in user is different from the one being added
if active_user_type != Profile.objects.get(user=User.objects.get(username = new_contact)).usertype:
return "valid"
else:
return "wrong type"
else:
return "does not exist"
_________THINGS I'VE TRIED TO RESOLVE THIS (but failed):_______________
deleting db
deleting local repository and recloning, and deleting db
makemigrations auth and makemigrations (there were no
migrations to make)
using --fake (as suggested in
Django 1.8 test issue: ProgrammingError: relation "auth_user" does not exist)
turning computer on an off again (as you can see, I'm pretty desperate)
Ok, so it turned out that some migrations were being skipped (?) when calling python manage.py makemigrations so I had to specify which app that I wanted to make migrations for. Calling python manage.py makemigrations grams (my target app name) fixed the problem.

Django Exception : AppRegistryNotReady("Models aren't loaded yet.")

I found a lot of content on the AppRegistryNotReady Exception, but none of them seem defenitive. I just wanted my 2 cents of info on the topic.
My django project was working fine. I created a new app, and created the following model. No view, no urls nothing. Just a model.
from __future__ import unicode_literals
from django.db import models
# Create your models here.
from django.conf import settings
from django.core.exceptions import ValidationError
from django.contrib.auth import get_user_model
User = get_user_model()
class File(models.Model):
path = models.TextField() #The path does not include MEDIA_ROOT, obviously
filename = models.CharField(max_length=500)
# file = models.FileField(upload_to=upload_to)
file = models.FileField(upload_to=path+filename)
user = models.ForeignKey(settings.AUTH_USER_MODEL, models.PROTECT) #Protects User from being deleted when there are files left
def clean(self):
#Check if path has a trailing '/'
if self.path[-1]!='/':
self.path = self.path+"/"
if self.filename[0]=='/':
self.filename = self.filename[1:]
#Get the full path
username = self.user.__dict__[User.USERNAME_FIELD] #Need to do this the roundabout way to make sure that this works with CUSTOM USER MODELS. Else, we could have simply went for self.user.username
self.path = "tau/"+username+"/"+self.path
def save(self, *args, **kwargs):
self.full_clean()
return super(File, self).save(*args, **kwargs)
def __str__(self):
if path[-1]=='/':
text = "\n"+str(path)+str(filename)
else:
text = "\n"+str(path)+"/"+str(filename)
return text
Then I tried to makemigrations on the model. And ended up with the following error.
(test) ~/Workspace/WebDevelopment/Django/test/stud$python manage.py makemigrations
Traceback (most recent call last):
File "manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "/home/raghuram/Workspace/WebDevelopment/Django/test/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line
utility.execute()
File "/home/raghuram/Workspace/WebDevelopment/Django/test/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 341, in execute
django.setup()
File "/home/raghuram/Workspace/WebDevelopment/Django/test/local/lib/python2.7/site-packages/django/__init__.py", line 27, in setup
apps.populate(settings.INSTALLED_APPS)
File "/home/raghuram/Workspace/WebDevelopment/Django/test/local/lib/python2.7/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models(all_models)
File "/home/raghuram/Workspace/WebDevelopment/Django/test/local/lib/python2.7/site-packages/django/apps/config.py", line 199, in import_models
self.models_module = import_module(models_module_name)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/home/raghuram/Workspace/WebDevelopment/Django/test/stud/tau/models.py", line 10, in <module>
User = get_user_model()
File "/home/raghuram/Workspace/WebDevelopment/Django/test/local/lib/python2.7/site-packages/django/contrib/auth/__init__.py", line 163, in get_user_model
return django_apps.get_model(settings.AUTH_USER_MODEL)
File "/home/raghuram/Workspace/WebDevelopment/Django/test/local/lib/python2.7/site-packages/django/apps/registry.py", line 192, in get_model
self.check_models_ready()
File "/home/raghuram/Workspace/WebDevelopment/Django/test/local/lib/python2.7/site-packages/django/apps/registry.py", line 131, in check_models_ready
raise AppRegistryNotReady("Models aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
Just for the sake of completing the test, I changed my model to this,
class File(models.Model):
file = models.FileField()
And that stopped the exception. So my guess is that the Exception was being raised by this.
from django.contrib.auth import get_user_model
User = get_user_model()
But I need to use that, since Im working with custom User Model. Any idea on how I can make it happen?
AbstractBaseUser provides a get_username() method which you can use instead. It practically does the same as what you're doing: return getattr(self, self.USERNAME_FIELD).
class File(models.Model):
...
def clean(self):
#Check if path has a trailing '/'
if self.path[-1]!='/':
self.path = self.path+"/"
if self.filename[0]=='/':
self.filename = self.filename[1:]
#Get the full path
username = self.user.get_username()
self.path = "tau/"+username+"/"+self.path
The reason your original method failed is because get_user_model() is executed when the module is first imported, at which time the app registry is not fully initialized. If you need to use get_user_model() in a models.py file, you should call it within a function or method, not at the module level:
class File(models.Model):
...
def clean(self):
User = get_user_model()

Django does't recognize User as an attribute in ModelForm

I am trying to make an edit profile form and I want the default input values to be the current user data. For example in the username field the default value will me the current user username. So I made a Model Form and I tryed this:
from __future__ import unicode_literals
from django import forms
from django.forms import ModelForm, Textarea
from django.db import models
from django.contrib.auth.models import User
class User_Edit(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'email']
widgets = {
'username': Textarea(attrs={'value': model.username })
}
But Django says: AttributeError: type object 'User' has no attribute 'username'
Also this is the full Traceback:
Traceback (most recent call last):
File "/home/sebastian/Spartan/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
fn(*args, **kwargs)
File "/home/sebastian/Spartan/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 109, in inner_run
autoreload.raise_last_exception()
File "/home/sebastian/Spartan/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 249, in raise_last_exception
six.reraise(*_exception)
File "/home/sebastian/Spartan/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
fn(*args, **kwargs)
File "/home/sebastian/Spartan/local/lib/python2.7/site-packages/django/__init__.py", line 18, in setup
apps.populate(settings.INSTALLED_APPS)
File "/home/sebastian/Spartan/local/lib/python2.7/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models(all_models)
File "/home/sebastian/Spartan/local/lib/python2.7/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/home/sebastian/Documents/project-spartan/profiles/models.py", line 8, in <module>
class User_Edit(forms.ModelForm):
File "/home/sebastian/Documents/project-spartan/profiles/models.py", line 9, in User_Edit
class Meta:
File "/home/sebastian/Documents/project-spartan/profiles/models.py", line 13, in Meta
'username': Textarea(attrs={'value': model.username })
AttributeError: type object 'User' has no attribute 'username'
Basically, you shouldn't be setting the value of each field in the Meta class. You can initialize a form from an object representing the user you're looking for, so in your view you'd have:
#Whatever happens in your view function before you create the form
user_obj = User.objects.get(username = target_username,
email=target_email) #Or how ever else you want to get the user in question
form = User_EditForm(instance = user_obj)
#Rest of your view
To make your life easier, you might want to look at using the UpdateView instead, depending on your exact use case.

Cannot Create Superuser After Add Custom User Model

I create CustomUser class that extends AbstractUser, and add a ForeignKey field that reference to City Model
class City(models.Model):
created_dt = models.DateTimeField("Created Time", auto_now_add=True)
code = models.CharField(max_length=64, unique=True)
name = models.CharField(max_length=64)
class CustomUser(AbstractUser):
city = models.ForeignKey(City)
REQUIRED_FIELDS = ['city']
I add the CustomUser to setting:
AUTH_USER_MODEL = "myapp.CustomUser"
When I tried to syncdb, it prompted me to create super user, when I fill in the city, I got this error:
City: 1
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/var/www/uib_webservice/.virt1/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 399, in execute_from_command_line
utility.execute()
File "/var/www/uib_webservice/.virt1/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 392, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/var/www/uib_webservice/.virt1/local/lib/python2.7/site-packages/django/core/management/base.py", line 242, in run_from_argv
self.execute(*args, **options.__dict__)
File "/var/www/uib_webservice/.virt1/local/lib/python2.7/site-packages/django/core/management/base.py", line 285, in execute
output = self.handle(*args, **options)
File "/var/www/uib_webservice/.virt1/local/lib/python2.7/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 116, in handle
user_data[field_name] = field.clean(raw_value, None)
File "/var/www/uib_webservice/.virt1/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 255, in clean
self.validate(value, model_instance)
File "/var/www/uib_webservice/.virt1/local/lib/python2.7/site-packages/django/db/models/fields/related.py", line 1201, in validate
using = router.db_for_read(model_instance.__class__, instance=model_instance)
File "/var/www/uib_webservice/.virt1/local/lib/python2.7/site-packages/django/db/utils.py", line 250, in _route_db
return hints['instance']._state.db or DEFAULT_DB_ALIAS
AttributeError: 'NoneType' object has no attribute '_state'
can someone explain to me why ?
I'm still a newbie in django, thanks
You can't set a required field to be a foreign key according to the docs. There's a ticket open with something similar to what you're encountering. I'd suggest subclassing CustomUserManager and override the create_superuser method on it, then use it for the objects manager on your CustomUser model.

Categories

Resources