Django does't recognize User as an attribute in ModelForm - python

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.

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.

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: model OneToOneField with User can't add default value

I have an model and I want to add an OneToOneField to hold the creator of an object:
models.py
creator = models.OneToOneField(User, blank=True,
default=User.objects.filter(
username="antoni4040"))
I already have a database with items and just want the default value to be the admin user, which has the username "antoni4040". When I try to migrate without the default field it asks for a default value, so I can't get away with it. But here's what I get when running makemigrations:
Migrations for 'jokes_app':
0008_joke_creator.py:
- Add field creator to joke
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 150, in handle
self.write_migration_files(changes)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 178, in write_migration_files
migration_string = writer.as_string()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 167, in as_string
operation_string, operation_imports = OperationWriter(operation).serialize()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 124, in serialize
_write(arg_name, arg_value)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 88, in _write
arg_string, arg_imports = MigrationWriter.serialize(_arg_value)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 433, in serialize
return cls.serialize_deconstructed(path, args, kwargs)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 318, in serialize_deconstructed
arg_string, arg_imports = cls.serialize(arg)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 517, in serialize
item_string, item_imports = cls.serialize(item)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 540, in serialize
"topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: <User: antoni4040>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/1.9/topics/migrations/#migration-serializing
What am I doing wrong?
You are using the queryset User.objects.filter(username="antoni4040"). To get a model instance, you would use User.objects.get(username="antoni4040").
However, you shouldn't use a a model instance for as the default in the model field. There's no error handling if the user does not exist in the database. In fact, if models.py is loaded before you run the initial migrations, then the User table won't even exist so the query will give an error.
The logic to set the default user should go in the view (or Django admin) instead of the models file.
In the admin, you could define a custom form that sets the initial value for the creator field.
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
try:
user = User.objects.get(username="antoni4040")
kwargs['initial']['creator'] = user
except MyModel.DoesNotExist:
pass
super(MyModelForm, self).__init__(*args, **kwargs)
Then use that model form in your admin.
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
...
If you really wanted to do this you can open up a shell and get the id for that User, then set the default to that.
The problem is, why would you do that? The first time you add a model it will use the default correctly. The second time you try to do that, it will fail because it's one to one, not many to one, so it will fail.

Using OneToOneField in Django

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'

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