On Sun, Apr 10, 2016 at 5:12 AM, Andrew Chiw <randomshinichi4...@gmail.com>
wrote:

> class Client(UserenaBaseProfile):
>     def __str__(self):
>         return self.name
>
>     user = models.OneToOneField(User,
>                                 unique=True,
>                                 verbose_name=_('Django Login'),
>                                 related_name='client')
>
>     name = models.CharField(max_length=100, unique=True, default=user.name
> )
>
>
> The title says it all - this class is supposed to have a OneToOneField
> relationship with a Django User, and through django-toolbar I've seen that
> when a user signs up, the Django User is created first and then my Client
> class. But how do I get the Client class to have the same name as the
> Django User's name?
>

The reason this doesn't work the way you want is because Django is
specifically designed not to work that way. The 'default' keyword is a
database table default, not a Python code default. This means that the
value for 'default' is calculated to a final value once, and when the
column is created, that value is used as the 'default' and programmed
directly into the database table configuration. Django does not reference
this argument except during migrations (AFAIK). And, given that it is a
class definition, the value is only calculated once at the start of the
thread. Since it is only a class definition at run time (you are not
processing an object when Django starts), your default turns out to be a
OneToOne field object with no data (not a User object or anything useful),
which would eventually translate into some string usable as a database
default, hopefully. I ran a version of this quickly in the shell, and
client.name.default ended up being None. Not sure if that is what happens
during a migration, since my shell is probably running in a vacuum compared
to a full makemigration run.

Mike's answer about overriding the save() method and adding a helper
function for your model is the way to go. It depends on the logic you want
to implement, but I would expand his example a bit more to say that you
first try to retrieve self.name, if that is empty then return
self.user.username and/or self.user.firstname/lastname. This would assume
setting a default='' on your name field. This gives you the flexibility of
grabbing either the 'name' or the username if 'name' isn't available, and
allowing you to build queries down the road to find all of the users that
have not specified a name for themselves.

With your strategy, assuming it worked, you wouldn't be able to
differentiate between users with no name assigned, and those who used their
usernames as their "name" intentionally. You would also need to run an
extra calculation in your ORM/DB query that would compare the value of
self.name and self.user.username to see if there was a difference, which is
expensive and difficult to maintain.

I would also suggest you add a null=True to your user field, since you
likely will never have a Client object that is not associated to a User
object.

There is also a get_full_name() and get_short_name() on the User class that
you can use, possibly instead of the "name" field you are creating.

-James

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/CA%2Be%2BciWE1PS5J4FyTvGnAKK8ha-DO2hqTERnA7R%3DPRKGC4FGfA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to