I've created a custom user model using abstractuser titled employee.
class Employee(AbstractUser):
username = models.CharField(max_length = 30)
first_name = models.CharField(max_length = 30)
last_name = models.CharField(max_length=30)
email = models.CharField(max_length=255)
password = models.CharField(max_length=30)
user_type = models.ForeignKey('UserProfile', null = True)
status = models.CharField(max_length = 30, default='Not Verified',)
def __str__(self):
return self.first_name + ' ' + self.last_name
That is my models.py pertaining to Employee
On the Admin page I see this - Admin Page
Learningsys is my app name.
How do I make it so that I see ''Employee or preferably 'Employees' under my app name instead of 'Users' and why does it show Users in the first place? I suspect it is because I am technically creating a 'Custom User' but would like clarification regardless.
Thanks,
Rohan.
You need to use verbose_name_plural meta option to change model's plural name on admin page:
class Employee(AbstractUser):
...
class Meta:
verbose_name_plural = 'Employees'
The default value of verbose_name_plural for AbstractUser is users so you inherited it with other AbstractUser's properties.
Related
Hello I am pretty new to Django and don't get yet fundamental ideas of Users.
I was able to create a registration page to create users which are shown on the admin page in the "Authentication and AUthorization -> Users".
Now I want the users to logg in and create their profiles. They should add some additional information like name, bio, picture etc.
Every user should be able to add and see its own profile.
To do that I created a model:
class Profile(models.Model):
firstname = models.CharField(max_length=50)
lastname = models.CharField(max_length=50)
bio = models.TextField()
profile_pic = models.ImageField(upload_to="images/")
def __str__(self):
return self.firstname + ' | ' + self.lastname
In my view and the html I am able to add these informations to the model.
But HOW exactly can I relate this "Profile"-Model to the individual user? What do I miss here?
You can do this via adding a OneToOneField relationship between Profile and the default User:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
firstname = models.CharField(max_length=50)
lastname = models.CharField(max_length=50)
bio = models.TextField()
profile_pic = models.ImageField(upload_to="images/")
def __str__(self):
return self.firstname + ' | ' + self.lastname
You can make a OneToOneField to the AUTH_USER_MODEL setting [Django-doc]. This settings contains a string with the qualified name of the user model. This is better than linking to the User model of django.contrib.auth.models.User, because if you later create a custom user model, the references to that user model will be updated:
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
# …
For more information, see the referencing the user model section of the Django documentation.
So I have users whose profiles are automatically created after user creation with the help of Django Signals
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
class Meta:
db_table = "Profile"
class Liked_Songs(models.Model):
track_name = models.ForeignKey(Profile , on_delete= models.CASCADE , related_name="track")
artiste_name= models.ForeignKey(Profile, on_delete= models.CASCADE , related_name="artiste")
album_name = models.ForeignKey(Profile, on_delete= models.CASCADE, related_name= "album")
class Meta:
db_table = "Liked Songs"
def __str__(self):
return self.track_name
In this Liked_Songs model, my views.py accesses an API and my aim is to allow all fields in that model to be populated with data from the API. So there will be multiple track_name etc received. So each Profile can have many track names etc. Is the ForeignKey appropriate for this?
However, when I use this route below, i get an error I have stated in the problem description.
Views.py
def liked(request):
try:
if "access_token" in request.session:
sp = Spotify(auth = request.session.get("access_token"))
liked = sp.current_user_saved_tracks(limit=30)['items']
for idx, item in enumerate(liked):
track = item['track']["name"]
artist= item["track"]["artists"][0]["name"]
album = item["track"]["album"]["name"]
Liked_Songs.objects.create(
track_name= track,
artiste_name= artist,
album_name = album
).save()
except SpotifyException:
return redirect(reverse("login"))
you are storing profile id in track so you cannot pass name in it so try to pass profile id in it
try this track_name_id = profile_id
When the form saves I want to save the object with a reference to the user's Profile page. So each profile can list every offer made by the user,
see Class based views query: get objects referenced by another model
ofertoj_oferto.profile_id may not be NULL
My model of "Oferto" contains a ForeignKey to the User's Profile. Right now I don't have an idea how i can tell the system "Get the logged in User's Profile and save this Ofeto with that ID"
Maybe there is some way where I lookup the profile associated with the user and don't need both user and profile on the Oferto model.
But I will still need to a list of every oferto made by the user on there profile
profiles.models
class Profile(BaseInfo):
bio = models.TextField(max_length=15000000)
user = models.ForeignKey(User)
views.py
class OfertoCreateView(LoginRequiredMixin, Turtle_CreateView):
model = Oferto
action = "created"
form_class = OfertoCreateForm
forms.py
class OfertoCreateForm(Turtle_Form):
class Meta:
model = Oferto
fields = ("name",
"description",
"tags",
"time",
"requirements",
"location",
"image",)
models.py
class Oferto(models.Model):
user = models.ForeignKey(User)
profile = models.ForeignKey(Profile)
name = models.CharField(max_length=150)
description = models.TextField(max_length=3000)
time = models.DecimalField(max_digits=10000000, decimal_places=2, null=True)
stelo = models.DecimalField(max_digits=10000000, decimal_places=2, null=True)
location = models.TextField(max_length=3000)
slug = AutoSlugField(('slug'), max_length=128, unique=True, populate_from=('name',))
tags = tagging.fields.TagField()
image = models.ImageField(upload_to='Ofertoj', blank=True, null=True)
requirements = models.TextField(max_length=550000, blank=True, null=True)
def get_absolute_url(self):
return reverse('oferto_detail', kwargs={'slug': self.slug})
def __unicode__(self):
return self.name
def get_tags(self):
return Tag.objects.get_for_object(self)
In your view/form/model save area: calling request.user returns a User object you can send to a model's ForeignKey field
This question is extension of Better Django UI for one to many relationship.
modles.py
from django.db import models
# Create your models here.
class Dude(models.Model):
name = models.CharField(blank=False, null=False, max_length=100, unique=True)
def phones(self):
# use reverse relation to get a list ofall recorded numbers
phone_numbers = self.phonenumber_set.values_list('number', flat=True)
phone_count = self.phonenumber_set.count()
return "This user have %s numbers recorded: %s" % (phone_count, ', '.join(phone_numbers))
def __unicode__(self):
return u"%s" % self.name
class PhoneType(models.Model):
name = models.CharField(blank=False, null=False, max_length=100, unique=True)
class PhoneNumber(models.Model):
dude = models.ForeignKey(Dude)
number = models.CharField(blank=False, null=False, max_length=100, unique=True)
type = models.ForeignKey(PhoneType)
admin.py
from django.contrib import admin
# Register your models here.
from TestingDjango.apps.one_to_many.models \
import Dude, PhoneNumber
class PhoneNumberInline(admin.TabularInline):
model = PhoneNumber
extra = 1
class DudeAdmin(admin.ModelAdmin):
pass
list_display = ('name', 'phones')
inlines = [ PhoneNumberInline, ]
class PhoneNumberAdmin(admin.ModelAdmin):
pass
list_display = ('dude', 'number')
admin.site.register(Dude, DudeAdmin)
When I add new Dude I can only select existing PhoneType. There is no "+" button like for other ForeignKey fields. I suspect that that is duo to this one-to-many relationship. So how to add "+" button for PhoneType ?
You will need to register PhoneNumberAdmin to make it accessible to Django's admin, then it will give you the '+' option to add more.
insert
admin.site.register(PhoneNumber, PhoneNumberAdmin)
at the bottom of the file
Is it possible to create a verbose name for the actual Class model?
class User(models.Model):
fname = models.CharField(max_length=50, verbose_name = 'first name')
So in the admin panel it will be referenced by its verbose name and not 'user' ?
class User(models.Model):
fname = models.CharField(max_length=50, verbose_name = 'first name')
class Meta:
verbose_name = "users"
Source: https://docs.djangoproject.com/en/2.1/topics/db/models/#meta-options
verbose_name and verbose_name_plural both the properties of Meta class are very important to modify the default behaviour of Django to display the name of our models on Admin interface.
You can change the display of your model names using on Admin Interface using verbose_name and verbose_name_plural properties and model fields names using keyword argument verbose_name.
Please find the below 2 examples.
Country model:
class Country(models.Model):
name = models.CharField(max_length=100, null=False, blank=False, help_text="Your country", verbose_name="name")
userid = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f"Country {str(self.id)} - {self.name}"
class Meta:
verbose_name = "Country"
verbose_name_plural = "Countries"
If you will not specify verbose_name_plural then Django will take it as Countrys which does not look good as we want it as Countries.
This better fits in the following type of Model.
Gender model:
class Gender(models.Model):
name = models.CharField(max_length=100, null=False, blank=False, help_text="Gender", verbose_name = "name")
userid = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f"Gender {str(self.id)} - {self.name}"
class Meta:
verbose_name = "Gender"
You could add a "verbose_name_plural" to the "Meta" class too.
To alter admin model without polluting the model itself, you can utilize a proxy admin model, like this:
# admin.py
from . import models
class Users(models.User):
class Meta:
proxy = True
class UsersAdmin(admin.ModelAdmin):
...
admin.site.register(Users, UsersAdmin)
ConfigAbility._meta.verbose_name = 'config ability'
ConfigAbility._meta.verbose_name_plural = 'config ability'
I did explore this, but don't know whether it's the thing you need. I put those codes in class ConfigAbilityAdmin in Admin.py. Then, the result:
enter image description here
With this approach, you don't need to config Meta method in model class, especially when model class's code is generated from inspectdb...