I want to assign a User to a Model in django, I created a custom User model and sign-up/sign-in Forms but now I want to Assign a User model to another model named Customer whenever a new user is Created Here he the Customer model
class Customer(models.Model):
id = models.AutoField(primary_key=True)
User = models.OneToOneField(
Account, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, default='0', null=True, blank=True)
address = models.CharField(
max_length=200, default=' ', null=True, blank=True)
city = models.CharField(max_length=200, default=' ', null=True, blank=True)
def __str__(self):
if self.name == None:
return "ERROR-CUSTOMER NAME IS NULL"
return self.name
Note: I can assign the User manually in the Database and It lists All the Users but I want it to do it itself when a new user is created
I think it would be better to extend the User model, and add more fields rather than creating a new model (which has a User onetoonefiled in it).
Something like this:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
This is the kind of approach I use in my projects.
Here you have the default User model fields:
User model default fields
You don't need to add these in your Profile class.
I based this on this article: How to extend User Django Model
don't forget to add to the admin.py:
from django.contrib import admin
from .models import Profile
# Register your models here.
admin.site.register(Profile)
to see the Profiles in the admin page
Got it fixed by setting the user in the Customer model when a user is created
Customer.objects.create(user=request.user, name=username, email=email, phone=phone)
Related
I'm working on Property Management django app where my base model is Tenant with all basic info like name, surname, email etc. Willing tenants will be able to create user account so they can log in and book Gym/Cinema, but not all Tenants will need to have user account. My problem is:
How can I create new user accounts based on existing Tenant objects? Obviously user will have Tenant ForeignKey but how can I extract Tenant.name, Tenant.surname etc to more than 1 field in my user model?
ForeignKey only gives me reference to object but can I somehow access certain fields of that object during creation of new user so I make sure that Tenant.email is the same as user.email?
Edit
tenancy = (('Tenant', 'Tenant'),('Owner', 'Owner'), ('Other', 'Other'))
class Tenant(models.Model):
name = models.CharField(max_length=15, null=True, blank=False)
surname = models.CharField(max_length=30, null=True, blank=False)
email = models.EmailField(max_length=50, unique=True)
phone_number = models.CharField(max_length=20, null=True, blank=True, unique=True)
flat = models.ForeignKey(Flat, on_delete=models.PROTECT)
status = models.CharField(max_length=10, choices=tenancy, null=True, blank=False)
stay_length = models.CharField(max_length=20, null=True, blank=False)
pet_licence = models.CharField(max_length=20, null=True, blank=False)
additional_notes= models.TextField(max_length=300, blank=True)
date_added = models.DateField(auto_now_add=True, null=True)
moved_out = models.BooleanField(default=False)
date_moved_out= models.DateField(auto_now_add=False, null=True)
class Meta:
unique_together = ('name', 'surname',)
def __str__(self):
return f'{self.name} {self.surname}'
Now I'd like to create user account model where name, surname, email, phone_number and flat will be ForeignKeys of Tenant model. Is it even possible to have 4 ForeignKeys from 1 object populating new model?
I've tried playing around with ForeignKey.limit_choices_to, ForeignKey.related_name, ForeignKey.to_field (this was close but field related to has to be unique which doesn't work for my case) but everything gives errors. I just want to find out if it's even possible that more than 1 ForeignKey of 1 object can be directed to multiple different fields of new model object.
I would approach it in a way that the foreign key is in Tenant, instead of User, and define it as a nullable one-to-one. This way you keep your User model free of foreign keys:
class Tenant(models.Model):
user = models.OneToOneField(
User,
related_name='tenant',
on_delete=models.CASCADE,
null=True,
blank=True,
default=None,
)
Then to create the related user, you can add a method in your Tenant model like so:
class Tenant(models.Model):
...
def create_user(self):
if not self.user:
user = User.objects.create(
first_name=self.name,
last_name=self.surname,
...
)
self.user = user
self.save()
Have a look at the example from the docs here.
You can use to_field to create fkeys to non-pk fields of another model, however, those fields need to have a unique constraint (i.e. unique=True) - which seems unlikely for name/surname.
It sounds like you want a transparent access from the User model to the Tenant models fields, and that is not possible.
You can create a fkey from User to Tenant:
class User(models.Model):
tenant = models.OneToOneField(Tenant, null=True, blank=True, related_name='user')
...
and then access the fields with
user = User.objects.get(...)
user.tenant.surname
to keep the fields in sync you can override the save() method:
class Tenant(...)
...
def save(self, *args, **kwargs):
if self.user:
self.user.last_name = self.surname
...
self.user.save()
super().save(*args, **kwargs)
aside: null=True indicates that the database should allow null in the field, blank=True says that the field can be empty in the admin interface. You should probably have null=True, blank=True in most cases.
Every user in my Django project has a list of Reports. I now want to display the user his list of reports. But how can I get all receipts which belong to a specific user?
Report-Model
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Report(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=False, null=False)
department = models.CharField(max_length=256, blank=False, null=False)
workshop = models.CharField(max_length=256, blank=False, null=False)
teacher = models.CharField(max_length=256, blank=False, null=False)
hours = models.IntegerField(blank=True, null=False, default=4)
date = models.DateField(blank=True, null=False)
For example, if you want to get the reports of the logged in user you can do the following.
reports = Report.objects.filter(user=request.user)
this should return all the reports of a user. Similarly change the request.user object to another user object and is should work fine as well.
Note - I am assuming "reports" and "receipts" are the same the thing here cause there's no mention of receipt attribute in your model.
I'm trying to make a Pastebin clone using Django.
In my models.py file, I have two models:
CustomUser which is inherited from AbstractUser
Snippet which is inherited from Model
from .helpers import url_shortner
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.username
class Snippet(models.Model):
id = models.CharField(primary_key=True, max_length=19, default=url_shortner, editable=False)
owner = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
title = models.CharField(max_length=50, default="Untitled")
content = models.TextField()
creation_date = models.DateTimeField(auto_now_add=True)
expiration_date = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
Now if there's a guest user want to make a snippet, as far as I know the owner field for this snippet should have a relation to AnonymousUser object so, How to implement it? Is there any kind of relations can relate Snippet object to these two models (CustomUser & GuestUser)? what is the best practice for this case?
Pastebin are using unique useID for guest users so that they can identify a user (without login).
When a guest user open first time their website they store a unique userID in browser local storage. after in further request they identify guest user by this userID.
In future If the user logs in then they search all content in database by userID and link with login user...
To make it...
firstly generate unique id ..
import uuid
quest_id = uuid.uuid4()
Send this guest_id to browser when user come first time in your
website.
get quest_id from browser in each request to identify a guest user
save all activity of guest user by guest_id in database
if guest user become login user then search all data by guest_id in
database and connect it with this logined user
To identify user is guest user or login user use ..
if request.user.is_authenticated:
print('this is login user')
make owner field in your model optional
and add a extra field guest_id
from .helpers import url_shortner
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.username
class Snippet(models.Model):
id = models.CharField(primary_key=True, max_length=19, default=url_shortner, editable=False)
owner = models.ForeignKey(CustomUser, null=true, on_delete=models.CASCADE)
title = models.CharField(max_length=50, default="Untitled")
content = models.TextField()
guest_id = models.CharField(max_length=100, blank=True)
creation_date = models.DateTimeField(auto_now_add=True)
expiration_date = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
if user is guest user then ..
Snippet.objects.create(owner=None ,guest_id=guest_id .....)
get guest_id from browser in each request
i hope this will helpful to you !!
You can do it with :
1. Change the models to :
`
from django.contrib.auth.models import User
class CustomUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.username
class Snippet(models.Model):
id = models.CharField(primary_key=True, max_length=19,
default=url_shortner, editable=False)
owner = models.ForeignKey(CustomUser, null=True,on_delete=models.CASCADE)
title = models.CharField(max_length=50, default="Untitled")
content = models.TextField()
creation_date = models.DateTimeField(auto_now_add=True)
expiration_date = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
`
2. To test in views.py, if the user is guest or no you can do it using:
if request.user.is_authenticated:
pass
==> This test returns false if the user is a GuestUser :)
models.py as below,
from django.db import models
from django.contrib.auth.models import User
class members(models.Model):
auto_id = models.AutoField(primary_key=True)
member_name = models.OneToOneField(User)
owner = models.ForeignKey('auth.User', related_name='webapi', on_delete=models.CASCADE)
father_name = models.CharField(max_length=25, blank=False, default='')
wife_name = models.CharField(max_length=25, blank=False, default='')
number_of_child = models.IntegerField(blank=True)
address_line_1 = models.CharField(max_length=40, blank=False, default='')
address_line_2 = models.CharField(max_length=40, blank=True, default='')
city = models.CharField(max_length=25, blank=False, default='')
class Meta:
ordering = ('member_name',)
Now The above has been linked with django auth Users table and in steriliser it shows the existing Django users and I have to choose one during the submit.
But my requirement is as a admin user I login and then provide the member_name manually which should automatically create a django user also
django-annoying has a feature for this, specifically AutoOneToOneField.
Sample from their github:
from annoying.fields import AutoOneToOneField
class MyProfile(models.Model):
user = AutoOneToOneField(User, primary_key=True)
This should automatically create a User.
Giving the following models...
class ProjectComment(RewardBase):
user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True)
class User (AbstractBaseUser):
email = models.EmailField()
class Profile(models.Model):
bio = models.CharField(max_length=80)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, unique=True)
From project I want to get the Users Profile bio, this is how I'm doing it....
def get_profile_bio(self):
return Profile.objects.get(user=self.user)
I now print a list of all projects I can get a profile bio, but is this the right way to do it? I'm worried that for every project it makes a new SQL call to the DB, is this correct?
class ProjectComment(RewardBase):
user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name="projects")
class User (AbstractBaseUser):
email = models.EmailField()
class Profile(models.Model):
bio = models.CharField(max_length=80)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, unique=True, related_name="profile")
Then you can fetch the users and the profiles:
projects = ProjectComment.select_related('user', 'user__profile').exclude(user__isnull=True).all()
for project in projects:
users = [user for user in project.user.all()]
And then:
for user in users:
profiles = [profile for profile in user.profile.all()]
Why do you have a unique constrain in your ForeignKey? if you need Uniquness create a OneToOneField