Using Django ORM to get a related model in a method - python

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

Related

django assign User to a model

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)

How to access ForeignKey-Objects in Django

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.

How to make relationship between a model and AbstractUser/AnonymousUser based on authentication?

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 :)

create a django user while creating a records for model

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.

Django best practice - referencing custom user or profile model

Based on Django's recommendation that information should be stored in a separate model if it's not directly related to authentication, I've created both a custom user model and a profile model in my app.
Something like:
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True
)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
location = models.ForeignKey(Location)
date_of_birth = models.DateField()
date_joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'location', 'date_of_birth']
class Profile(models.Model):
user = models.OneToOneField(User)
picture = models.ImageField(upload_to='profile_pictures/',
default='default.jpg')
bio = models.TextField(blank=True)
sex = models.CharField(max_length=10,
choices=(('Male', 'Male'),
('Female', 'Female'),
('No Comment', 'No Comment')),
default="No Comment")
occupation = models.CharField(max_length=100, blank=True)
What's the best practice for having other models refer to a user? For example, my app has a messaging system. In the Message model, is it best to have a foreignkey relation to Profile as opposed to User? Should the User model only be used for the purpose of authentication?
I think you can relate the models to User and use related name to access profile.
This makes your models not depend directly on custom profile.

Categories