How to make a serializer for multiple users (student & teacher)? - python

Hello I am very new to Django Rest Framework and I am having a hard time with the serializer. I extended the User Model using Abstract User. I inserted two new fields which are is_student and is_teacher then I set both of the values to false as default. I then put them in there own model then just applied a one-to-one relation for each of them to the user model. My problem is with the serializer. How do I make a serializer out of this. I want the student and teacher have relation with the user model as well as having the ability to do http actions such as get, post, put, etc.
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.conf import settings
# Create your models here.
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
class Course(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
price = models.FloatField()
def __str__(self):
return self.name
class Student(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
age = models.IntegerField()
address = models.CharField(max_length=200)
def __str__(self):
return self.user.username
class Teacher(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
description = models.TextField()
course_teaching = models.ForeignKey(Course, on_delete=models.CASCADE)
students = models.ManyToManyField(Student)
def __str__(self):
return self.user.username

Check out an example of this type of serializer here: https://github.com/imagineai/create-django-app/blob/master/todoapp/serializers.py

Related

'project.Account' has no ForeignKey to 'project.Object': How to link an account model to the objects of a project?

I am trying to create an announcement website (All) that can be visible to others (the Users, for which I added an Account). For this I wanted to modify a little the user profile to add fields like telephone, email address...
So I modified admin.py:
from django.contrib import admin
from .models import Todo, Account
from django.contrib.auth.models import User
class AccountInline(admin.StackedInline):
model = Account
can_delete = False
verbose_name_plural = 'Accounts'
class TodoAdmin(admin.ModelAdmin):
readonly_fields = ('created',)
inlines = (AccountInline, )
admin.site.unregister(User)
admin.site.register(Todo, TodoAdmin)
But got back:
<class 'todo.admin.AccountInline'>: (admin.E202) 'todo.Account' has no ForeignKey to 'todo.Todo'.
So I added a ForeignKey to Todo with account = models.ForeignKey(Account, on_delete=models.CASCADE):
from django.db import models
from django.contrib.auth.models import User
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.CharField(max_length=100)
firstname = models.CharField(max_length=30)
lastname = models.CharField(max_length=50)
company = models.CharField(max_length=5)
def __str__(self):
return self.user.username
class Todo(models.Model):
title = models.CharField(max_length=100)
datetime = models.DateTimeField()
memo = models.TextField(blank=True)
created = models.DateTimeField(auto_now_add=True)
datecompleted = models.DateTimeField(null=True, blank=True)
important = models.BooleanField(default=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
def __str__(self):
return self.title
But I still have the error, and I don't have any Users in the admin panel anymore
You accidentally wrote unregister for Users in your admin.py file. It should be admin.site.register(User)
You misinterpretted the error: the error states that you don't have a foreign key in your Account model to Todo.
This means your inline admin code isn't correct as it's expecting the other way around.

Django admin page not showing user models

My admin page is working fine except when logged in it is not showing any user models. It is hindering my work as I cannot manage users.
I have made custom models as shown below.
Database is MySQL.
models.py
class User(AbstractUser):
is_customer = models.BooleanField(default=False)
is_restaurant = models.BooleanField(default=False)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
food_pref = models.CharField(max_length=10, default='veg')
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
restaurant_name = models.CharField(max_length=100, blank=False)
Regisrar your models inadmin.py file.
from . models import Model_Name
Then you can register your models in two ways:
I) admin.site.register(Model_Name)
II)
#admin.register(Model_Name)
Class Xyz(admin.ModelAdmin):
pass
Second method gives you more flexibility like list_display, list_filter, date_hierarchy, etc. for customising your Admin section/site.
You can look more about customising admin site at https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#module-django.contrib.admin
Have You registered them in admin.py?
from .models import ModelName
admin.site.register(ModelName)

the model field's form disappears in django admin

I have two models, which are User and Record. Each has several fields.
from django.db import models
class User(models.Model):
openid = models.CharField(max_length=20)
nickname = models.CharField(max_length=20,null=True)
def __str__(self):
return self.nickname
class Record(models.Model):
expression = models.CharField(max_length=100)
user = models.ForeignKey(User)
time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.expression
I register them in admin.py
from django.contrib import admin
from .models import User,Record
class RecordAdmin(admin.ModelAdmin):
list_display = ('expression','user','time')
class UserAdmin(admin.ModelAdmin):
empty_value_display = "çİş"
list_display = ('openid','nickname')
admin.site.register(User,UserAdmin)
admin.site.register(Record,RecordAdmin)
it works well in django admin initially. but one day, the fields of the Record model disppeared. It looks like
.
No field displays. It makes me unable to modify or add the values of the Record model. The other model User works well and all data exists in database. So why?
I think you just have to add on_delete=models.CASCADE in your ForeignKey Field. When you are using this kind of field, you have to specify the comportment when you make an update, a delete or anything else on this field.
So your script should be like this :
class Record(models.Model):
expression = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE)
time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.expression
This is the result :
Edit :
You can also modify null=True by default=null
class User(models.Model):
openid = models.CharField(max_length=20)
nickname = models.CharField(max_length=20,default=null)
def __str__(self):
return self.nickname

Efficient way to implement newsfeed

I am trying to build a simple social network.
Say I have two models: Status and my custom UserProfile model to implement followers/followings feature:
from django.contrib.auth.models import User
class Status(models.Model):
user = models.ForeignKey(User, related_name='statuses')
title = models.CharField(max_length=50)
status = models.TextField()
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "Status"
verbose_name_plural = "Statuses"
ordering = ('-created',)
get_latest_by = 'created'
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
followings = models.ManyToManyField(
'self', related_name='followers', symmetrical=False, blank=True)
What is the most efficient way to access newsfeed i.e. recent statuses of all of my(User) followings?
I am new to Django. Any help will be much appreciated.
Simply filter Status queryset by users that you are following. Query above will show all statuses for all users followed by user.
Status.objects.filter(user__followers=user)

Django REST Framework: change field names

My Django application provides readonly api access to the users of the site. I created a user profile model and use it in the serializer of the user model:
Model:
# + standard User Model
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
display_name = models.CharField(max_length=20, blank=True)
Serializer:
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = UserProfile
fields = ('display_name',)
class UserSerializer(serializers.HyperlinkedModelSerializer):
userprofile_set = UserProfileSerializer(many=False, label='userprofile')
class Meta:
model = User
fields = ('id', 'username', 'userprofile_set')
This works but the field userprofile_set looks ugly. Is it possible to change the field name?
To complement your answer, you can also make use of relationships' related names:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='profiles')
display_name = models.CharField(max_length=20, blank=True)
that way you can also use this in your code:
user = User.objects.last() #some user
user.profiles.all() #UserProfiles related to this user, in a queryset
user.profiles.last() #the last UserProfile instance related to this user.
May I recommend that you turn that ForeignKey into a OneToOneField? that way an user can have one and just one user profile, and you don't need to establish uniqueness:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
display_name = models.CharField(max_length=20, blank=True)
Oh, I can name the variable userprofile_set as I like. First I tested the name userprofile which conflicted. If I name the field profile it works. :)
class UserSerializer(serializers.HyperlinkedModelSerializer):
profile = UserProfileSerializer(many=False, label='userprofile')
class Meta:
model = User
fields = ('id', 'username', 'profile')

Categories