Making a foreign key User model extension in Django required - python

I am extending the Django User model to include a foreign key pointing at another model like so (just like it says in the Django docs):
models.py:
class Ward(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
# Extending the user model
class WardMember(models.Model):
user = models.OneToOneField(User)
ward = models.ForeignKey(Ward)
def __unicode__(self):
return self.ward.name
admin.py:
class WardMemberInline(admin.StackedInline):
model = WardMember
can_delete = False
verbose_name_plural = 'ward member'
# Define a new User admin
class UserAdmin(UserAdmin):
inlines = (WardMemberInline, )
admin.site.register(Ward)
# Re-register UserAdmin to get WardMember customizations
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
When I create a new user in the admin interface I want this new WardMember.ward extension to be required. Currently it's not enforcing that. Here's what happens:
Create user succeeds without a ward
Create other records as user succeed
Edit user now won't let me save unless there is a ward selected
I'd really like #1 above to fail.
I've tried figuring out how to override save() for User using a proxy object but that's not working. I looked into the pre_save signal but the docs explicitly say that's not for vetoing saves.
What is the right approach?
Additional information:
I'm using 1.4. I see that in 1.5 I can extend the user class but I'm not in a position to update to 1.5 just yet.
I ended up forging ahead with Django 1.5, but I'll leave this here in case someone has a final answer to contribute that works with 1.4.

In django 1.3.1 I use this code and works fine:
from django.contrib.auth.models import User
class FilterSearchQueries(models.Model):
title = models.CharField(max_length=250)
owner = models.ForeignKey(User)
place = models.CharField(max_length=250)
query = models.TextField()

Related

Do i need to update AUTH_USER_MODEL in my settings.py?

I am creating my own users, Restaurant and Customer. I have extended the AbstractUser class and then created a OneToOneField field for each user. I am wondering if I need to add the AUTH_USER_MODEL in my settings.py. And also wondering what that does exactly...
What I was planning on doing was adding to my settings.py:
AUTH_USER_MODEL = 'myapp.Customer','myapp.Restaurant'
Do I have the right idea here?
My models.py:
class User(AbstractUser):
is_restaurant = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
class Restaurant(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
restaurant_name = models.CharField(max_length=50)
def __str__(self):
return self.restaurant_name
class Customer(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
address = models.CharField(max_length=200)
def __str__(self):
return self.user.get_full_name()
No. AUTH_USER_MODEL isn't expecting a tuple, so this won't work.
In any case, Restaurant and Customer are not your user model; your subclassed User is. That's what you should be putting in that setting.
I would suggest create single user table instead of three different tables and add type as restaurant, customer, admin etc. And add only one table into settings file. this won't lead any further issues authentication etc. Having single user table is always robust. In your case having three tables seems not good to maintain.
========== UPDATE ===========
Create model for user named as CustomUser (or name which you feel better) and extends to User Model of Django using AbstractBaseUser,PermissionsMixin. like
class CustomUser(AbstractBaseUser): have all fields which user table has already. and add your desired table to bifurcate type of restaurant and
customer have type field with choices option.
For further help you can check section https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#substituting-a-custom-user-model

Indirect inline in Django admin

I have the following models:
class UserProfile(models.Model):
user = models.OneToOneField(User)
class Property(models.Model):
user = models.ForeignKey(User)
I would like to create a TabularInline displaying every Property connected to a particular UserProfile on its Django admin page. The problem here is, of course, that Property does not have a ForeignKey directly to UserProfile, so I cannot simply write
class PropertyTabularInline(admin.TabularInline):
model = Property
class UserProfileAdmin(admin.ModelAdmin):
inlines = (PropertyTabularInline,)
How can I easily do what I want?
You can overwrite the User admin page to display both the Profile and the Property models.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from myapp.models import *
class ProfileInline(admin.TabularInline):
model = Profile
class PropertyInline(admin.TabularInline):
model = Property
class UserAdmin(UserAdmin):
inlines = (ProfileInline, PropertyInline,)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
You can also remove any unwanted/unused User properties from being displayed (e.g. Groups or Permissions)
more here: https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#extending-the-existing-user-model
and here:
https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#a-full-example
class PropertyTabularInline(admin.TabularInline):
model = Property
def formfield_for_dbfield(self, field, **kwargs):
if field.name == 'user':
# implement your method to get userprofile object from request here.
user_profile = self.get_object(kwargs['request'], UserProfile)
kwargs["queryset"] = Property.objects.filter(user=user_profile)
return super(PropertyInLine, self).formfield_for_dbfield(field, **kwargs)
once this is done, you can add this inline to user UserProfileAdmin like:
class UserProfileAdmin(admin.ModelAdmin):
inlines = (PropertyTabularInline,)
Haven't tested it, but that should work.
It is achievable by making one change in your models.
Instead of creating OneToOne relationship from UserProfile to User, subclass User creating UserProfile. Code should look like that:
class UserProfile(User):
# some other fields, no relation to User model
class Property(models.Model):
user = models.ForeignKey(User)
That will result in creating UserProfile model that have hidden OneToOne relation to User model, it won't duplicate user model.
After doing that change, your code will work. There are some changes under the hood, like UserProfile no longer have it's own ID, you can access fields from User inside UserProfile and it's hard to swap User model using settings.AUTH_USER_MODEL (that will require creating some custom function returning proper type and changing migration by hand) but if this is not a problem for you, it may be good solution.

Django Relating Model to User

I want to relate the Model of the Note in my web app with the user that created it .I guess the relation should be Many-to-One.So that i can then filter data by user.Help my the right code , explain , do you thing this is the right method to use in order to have separate data for each user.I really want your opinion on that.
class Note(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
cr_date = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(........) <----- should be something like that
You can add that as foreign key to user model,
#if you are using user model provided by django contrib
from django.contrib.auth.models import User
class Note(models.Model):
#user other fields
owner = models.ForeignKey(User)

What is the best way to query for instances of django models with one to one relationships with users

Let's say you have a django model with a OneToOne / Unique ForeignKey relationship with a User, as show on the Django documentation on how to create a UserProfile.:
Now let's say you have a view method that takes a request you can get a user from. What is the best way to query for the profile associated with that user?
from django.contrib.auth.models import User
# sample user profile model associated with user
class UserProfile(models.Model):
likes_spam = models.BooleanField()
user = models.OneToOneField(User)
#view method
def forward_to_practice_home(request):
user = request.user
profile_for_user = #insert code here that would get the profile for that user
related_names are very helpful. If you change your user profile definition to:
class UserProfile(models.Model):
likes_spam = models.BooleanField()
user = models.OneToOneField(User, related_name='profile')
then you can use profile as follows:
def forward_to_practice_home(request):
user = request.user
profile_for_user = user.profile
UserProfile.objects.get(user=user)
You may use a special method called get_profile()
profile_for_user = user.get_profile()
Be reminded that you have to set the AUTH_PROFILE_MODULE in the settings.py
However, this is deprecated in Django 1.5 because it adds the support of user model customization

Django: "UserProfileRole.userProfile" must be a "UserProfile" instance

I'm having a strange riddle to solve:
I extended my django-1.4 user-objects with a UserProfile, as described at https://docs.djangoproject.com/en/dev/topics/auth/ and wanted to implement project-specific roles. So my models look like the following:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
projects = models.ManyToManyField(Project, through='UserProjectRole')
[...]
class UserProjectRole(models.Model):
userProfile = models.ForeignKey(UserProfile)
project = models.ForeignKey(Project)
group = models.ForeignKey(Group)
[...]
I needed to pass a css-class, so I created a model-form for UserProjectRole and implemented the userProfile-Field with a widget:
class ProjectRoleForm(forms.ModelForm):
userProfile = forms.ModelMultipleChoiceField(label='Users',
queryset=UserProfile.objects.all(),
widget=forms.SelectMultiple(attrs={'class': 'select-multiple'}))
class Meta:
model = UserProjectRole
The form is presented correctly, however, it's crashing during save-process with the following error
Cannot assign "[<UserProfile: MyUser>]": "UserProjectRole.userProfile" must be a "UserProfile" instance.
Does anyone have an idea?
My guess is it's because you are using a forms.SelectMultiple widget. Which gives you a list of UserProfile instances ( [<UserProfile: MyUser>] ) and not a single UserProfile instance which is of course required to set on a ForeignKey field (UserProjectRole.userProfile). Thus I suggest to try using a forms.Select widget instead.

Categories

Resources