I am new to programming Django, so I'm not sure if this is possible.
I have created a new CustomUser class:
class CustomUser(AbstractBaseUser):
email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
mobile = models.CharField(max_length=30, null=True)
first_name = models.CharField(max_length=50, null=True)
middle_name = models.CharField(max_length=50, null=True)
last_name = models.CharField(max_length=50, null=True)
date_of_birth = models.DateField(null=True)
Primary_address = models.CharField(max_length=50, null=True)
Primary_address_zipcode = models.CharField(max_length=5, null=True)
is_active = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
A few questions:
Question 1: I have redefine some of the fields that exists in the default User class (e.g. First Name, Last name, Date Joined). However, I didn't define Last_login. But last_login still shows up as a column in the admin page. But if I don't define First Name, Last Name and Date Joined in my new CustomUser, I get an error and doesn't show up in the admin page. Why is last login special?
Question 2: The default admin page has great UI for group and permission control. Is it possible to define my CustomerUser and still use/enable the default admin page?
Thanks.
you dont need to define all these fields that are already there in django. dont reinvent the wheel. what error are you getting? traceback?
using your customuser model has nothing to do with using default admin page. you can always use django admin page no matter what models you have. Or i dont understand what you really want to achieve.
Related
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)
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.
In my models, I added the class Source:
class Source(models.Model):
profile = models.ForeignKey('Profile', on_delete=models.CASCADE, null=True, default=False, blank=True, related_name='+')
project= models.ForeignKey('Project', on_delete=models.CASCADE, null=True, default=False, blank=True, related_name='+')
team = models.ForeignKey('Team', on_delete=models.CASCADE, null=True, default=False, blank=True, related_name='+')
department = models.ForeignKey('Department', on_delete=models.CASCADE, default=False, blank=True, null=True, related_name='+')
def __str__(self):
return str(self.id)
For testing purposes, I added a few entries for posts in the Django admin page,
and then went back into my classes: Post, Profile, Department, Team, and Project, and added:
sourceID = models.ForeignKey('Source', default='1', on_delete=models.CASCADE, related_name='+', null=False)
for each class.
My problem is that when I go in the Django admin page to alter the database (i.e. create a new post) I get the following error:
Also, when I go to migrate my changes, I keep getting this warning:
HINT: Configure the DEFAULT_AUTO_FIELD setting or the LeadsConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.
I would like to be able to create new entries in my database without the operational error. I've tried changing the null value = True, but this is counterintuitive and doesn't yield any change, surprisingly. I think the best way would be to delete the whole database, which I've tried to research and only found MYSql code solutions. What is the best course of action?
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 have the following code in models.py, note the function at the bottom that seeks to change the teacher_object in the admin panel to the username of the teacher instead.
class Teachers(models.Model):
email = models.CharField(max_length=50)
school_pin = models.CharField(max_length=11)
username = models.CharField(max_length=50)
pass_field = models.CharField(db_column='pass', max_length=100) # Field renamed because it was a Python reserved word.
fname = models.CharField(max_length=50, blank=True, null=True)
lname = models.CharField(max_length=50, blank=True, null=True)
oauth_provider = models.CharField(max_length=50, blank=True, null=True)
oauth_uid = models.CharField(max_length=100, blank=True, null=True)
verified = models.IntegerField(blank=True, null=True)
verificationcode = models.CharField(db_column='verificationCode', max_length=100, blank=True, null=True) # Field name made lowercase.
school_name = models.CharField(max_length=255, blank=True, null=True)
designation = models.CharField(max_length=255, blank=True, null=True)
date = models.DateField(blank=True, null=True)
membershipid = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.username
class Meta:
managed = False
db_table = 'teachers'
The admin panel still shows the teachers listed as Teachers object (1275) (and so on).
I have tried the following:
1. Running the makemigrations and migrate commands
2. Logging in and out of the admin panel
3. Refreshing and closing down CMD - restarting
None of the above has worked. There are no errors on running the server.
Python version: 3.7 Latest Django installation
Considerations:
1. I was using a legacy mysql database so reverse created the models. Could this be affecting anything?
2 I wonder if the class Meta (at the bottom) has any bearing on the error.
I also tried the following, but still no result:
def __str__(self):
return '%s %s' %(self.username,self.email)
For reference, and in case this is relevant here is my admin.py
from django.contrib import admin
# Register your models here.
from django.contrib import admin
from .models import Teachers
from .models import TeacherPins
admin.site.register(Teachers)
admin.site.register(TeacherPins)
Finally, as this is a reverse-generated model (from a legacy mysql) Django provided this advice at the start of the models.py file. Again, could this (not being done, e.g not having a primary key etc) have a bearing on the str method not working?
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
# * Rearrange models' order
# * Make sure each model has one field with primary_key=True
# * Make sure each ForeignKey has `on_delete` set to the desired behavior.
# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
Update:
I did try rearranging the order (of the classes) - would this make a difference? But still the object remained an object
I tried adding a primary key to both classes - this didn't work either
student_id = models.IntegerField(blank=True, null=True, primary_key=True)