Alter default django models tables generation - python

I'm trying to create two related models in django, a custom user model and a company model.
where one user belongs to one company and one company has many users.
class Company(models.Model):
name = models.CharField(max_length=255)
class User(AbstractBaseUser):
objects = UserManager()
id = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, unique=True)
name = models.CharField(max_length=67)
username = models.CharField(max_length=255, unique=True)
email = models.EmailField(max_length=255, unique=True)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
last_login = models.DateTimeField(auto_now=True)
date_joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_supuser = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
By default django generated two tables like this:
But I dont want any foreign keys directly on those tables, instead
i want a third auxiliary table with the two foreign keys from the models
like this:
How could I do something like that ?

Related

how to filter items in django

I have some users in my application where some are admin and some are suppliers, I will like to filter only those that are suppliers. I have tried using some queryset but I am not getting it. I will also like some recommendation where I can learn more about to filter objects in Django or python. Thanks
models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
# CUSTOM USER FIELDS
firstname = models.CharField(max_length=30)
lastname = models.CharField(max_length=30)
telephone = models.IntegerField(blank=True, null=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
class user_type(models.Model):
is_admin = models.BooleanField(default=False)
is_supplier = models.BooleanField(default=False)
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
if self.is_supplier == True:
return User.get_email(self.user) + " - is_supplier"
else:
return User.get_email(self.user) + " - is_admin"
views.py
def Viewsupplier(request):
suppliers = User.objects.filter(i am getting stuck here with the appriopriate filter)
context = {"suppliers":suppliers}
print(suppliers)
return render(request, 'core/view-suppliers.html', context)
You cann filter with:
suppliers = User.objects.filter(user_type__is_supplier=True)
If you define a relation (like a ForeignKey or OneToOneField), you can access the relation in reverse as well. If you do this in a query, It uses the related_query_name=… [Django-doc] as name for the relation in reverse. If you did not fill this in, it will take the related_name=… [Django-doc], and finally, as is here the case, default to the model name in lowercase.
We thus here filter the User objects such that we only retrieve Users for which there is a related user_type where is_supplier is True.

filtering a queryset based on the results of anoter one

So I have a model called post and one of its fields is a foreign key to user model, And i have another model called subscriptions which has 2 foreign keys one referring to the user and the other one referrs to another account and i want to filter the post queryset to only show posts from people where there is a subscription object where the user is subscribed to the creator of the post. My models look like this:
class post(models.Model):
creator = models.ForeignKey(Account,blank=False,null=False,on_delete=models.CASCADE)
...
class subscriptions(models.Model):
subscriber = models.ForeignKey(Account,blank=False,null=False,on_delete = models.CASCADE, related_name='subscriber')
subscribed_to = models.ForeignKey(Account,blank=False,null=False,on_delete = models.CASCADE, related_name='subscribed_to')
i tried doing this in the views
posts = post.objects.filter(creator__in = request.user.subscribed_to)
but it return nothing
This is my account model:
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
addresse = models.CharField(max_length=60)
city = models.CharField(max_length=50)
party_count = models.IntegerField(default=0)
verified = models.BooleanField(default=False)
profil_pic = models.ImageField(upload_to='profil_pics/',blank=True)
birthday = models.DateField(default=date.today())
date_joined = models.DateTimeField(verbose_name='date_joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last_login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email','first_name','last_name','addresse','birthday','city']
objects = MyAccountManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self,app_label):
return True
You can solve it in one query.
Post.objects.filter(creator__subscribed_to__subscriber=request.user)
After doing some research i ended up finding some infos that lead to:
subs = subscriptions.objects.filter(subscriber=request.user).values_list('subscribed_to')
posts = post.objects.filter(creator__in = subs

Extending Custom User Model - Multiple User Types in Django

I'm relatively new(er) to django but very excited to learn such a versatile framework. I'm working on a project where I will have 2 user types, account 1 and account 2. Account 2 will have the ability to "add a user" to their account. Think of account 2 as a company who can add users to their company.
So far I've extended the generic User model and have created a class for each of the account types but I'm not sure if I'm doing it correctly. Ultimately I will want to create a login/register form for each of the account types - similar to how ziprecruiter functions so some advice on how to approach that would be awesome too if possible.
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def __str__(self):
return self.email
class account1(User):
profile = models.ForeignKey(User, on_delete=models.CASCADE, related_name='+', null=True)
# account 2 fields here
first_name = models.TextField(max_length=30, blank=True)
last_name = models.TextField(max_length=30, blank=True)
location = models.TextField(max_length=30, blank=True)
class Meta:
db_table = 'account1_user'
class account2(User):
profile = models.ForeignKey(User, on_delete=models.CASCADE, related_name='+')
# account2 user fields here
class Meta:
db_table = 'account2_user'
Am I doing this correctly? What's the best approach to creating a login/registration form for each type of account? What's the best approach to creating a model that will allow for a user of a user type (if that makes sense)?
Rule of thumb is no matter what your business logic, always use one User model for your application. if you want multiple types of user then you could use attributes to determine user types. For example, in my application i want three types of user, Admin,Broker and Client. Here is how we can do this.
class UserManager(BaseUserManager):
def create_client(self, username, first_name, last_name, email, phone, password=None):
user = self.model(
username=username,
first_name=first_name,
last_name=last_name,
phone=phone,
email=self.normalize_email(email)
)
user.set_password(password)
user.is_client = True
user.save(using=self.db)
return user
def create_reseller(self, username, first_name, last_name, email, phone, password=None):
user = self.create_client(username, first_name, last_name, email, phone, password)
user.is_reseller = True
user.save()
return user
def create_admin(self, username, first_name, last_name, email, phone, password=None):
user = self.create_reseller(username, first_name, last_name, email, phone, password)
user.is_admin = True
user.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
is_superuser = None
REQUIRED_FIELDS = ["username", "first_name", "last_name", "phone"]
EMAIL_FIELD = "email"
USERNAME_FIELD = 'email'
objects = UserManager()
email = models.EmailField(unique=True)
username = models.CharField(max_length=DefaultModel.MAX_LENGTH)
first_name = models.CharField(max_length=DefaultModel.MAX_LENGTH)
last_name = models.CharField(max_length=DefaultModel.MAX_LENGTH)
phone = PhoneNumberField(unique=True)
is_admin = models.BooleanField(default=False)
is_reseller = models.BooleanField(default=False)
is_client = models.BooleanField(default=False)
# storing timestamps for users.
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
added_by = models.ForeignKey("self", models.CASCADE, default=None, null=True)
So what i did, i'm using custom UserManager Class which is responsible for generating User Model objects and i've implemented methods for generating for all types of users Client, Broker and Admin.
DefaultModel is actually class which i'm using as constants for setting default values for models. Here is what it looks like:
class DefaultModel:
MAX_LENGTH = 1000
MYSQL_UNIQUE_LENGTH = 255
If you don't know about objects in models you may learn about it from Django docs.
Custom User Models
Django Managers

How to expand User(AbstractBaseUser) with OnetoOneField?

I want relate my Profile model with User model from class AbstractUserModel with OnetoOneFields. Is it possible? Or any solution with this problem. Here my models.py
from django.db import models
#from django.contrib.auth.models import User
from django.contrib.auth.models import (
AbstractBaseUser
)
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
class Profile(models.Model):
#HERE
user = models.OneToOneField(AbstractBaseUser, on_delete=models.CASCADE)
nama_lengkap = models.CharField(max_length=100, blank=True, null=True)
tgl_lahir = models.DateField(null=True, blank=True)
alamat = models.CharField(max_length=255)
foto_profil = models.ImageField(upload_to='foto_profil',blank=True)
jabatan = models.ForeignKey(Jabatan, on_delete=models.CASCADE)
def __str__(self):
return "{} - {}".format(self.user, self.nama_lengkap)
when I migrate this, just show some errors message like this:
SystemCheckError: System check identified some issues:
ERRORS:
users.Profile.user: (fields.E300) Field defines a relation with model 'AbstractBaseUser', which is either not installed, or is abstract.
users.Profile.user: (fields.E307) The field users.Profile.user was declared with a lazy reference to 'auth.abstractbaseuser', but app 'auth' doesn't provide model 'abstractbaseuser'.
thanks in advance
you need to replace this
user = models.OneToOneField(AbstractBaseUser, on_delete=models.CASCADE)
with
user = models.OneToOneField(User, on_delete=models.CASCADE)
However I recommend you doing it different way:
Instead of creating second User model, extend existing one:
#models.py
class ProfileUser(AbstractUser):
extra_field = models.CharField(max_length=100)
username = models.CharField(max_length=20) # modifing existing field
```
```
#settings.py
AUTH_USER_MODEL = "app_name.ProfileUser"

django foreign key relationships

models.py
class Hub(models.Model):
name = models.CharField(max_length=150)
def __str__(self):
return self.name
class User(AbstractUser):
is_client = models.BooleanField(default=False)
is_trainer = models.BooleanField(default=False)
username = models.CharField('username', max_length=150, unique=True)
email = models.EmailField(unique=True)
hub = models.ForeignKey(Hub, on_delete=models.CASCADE, blank=True, null=True)
hub_position = models.CharField(max_length=150, default="")
mentor = models.ForeignKey('self', on_delete=models.CASCADE, blank=True,null=True)
terms = models.BooleanField(blank=True, default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'terms']
def get_absolute_url(self):
return reverse('student:dashboard', kwargs={'pk': self.pk})
Confused on how to design the models here. Each User can belong to exactly one Hub.A hub has one leader, many excoms and many members ,all of them belongs to User .The hubs are added from the admin side.Leader can accept hub joining requests from excoms and members.
I'd add the user position as a choice field to the User, so you get a nice select box in the Admin.
class User(AbstractUser):
USER_POSITIONS = ((0, 'Regular'), (1, 'Leader'), (2, 'Excom'))
hub = models.ForeignKey(Hub, on_delete=models.CASCADE, blank=True, null=True)
hub_position = models.IntegerField(default=0, choices=USER_POSITIONS, ...)

Categories

Resources