I am having an issue with django model that creates multiple tables for same class, it creates two table for same relation, it should create 3 table i.e users, groups, and user_groups but I having an extra table with name users_groups (note: an extra 's').
Seems an issue with verbose_name, db_meta or related_name
Full Code:
from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.utils.translation import ugettext_lazy as _
class UserManager(BaseUserManager):
"""Define a model manager for User model with no username field."""
pass
class CustomUser(AbstractUser):
"""Model representing a User with some extended fields and email as username field"""
username = None
email = models.EmailField(max_length=100, unique=True)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
ordering = ['email']
db_table = 'users'
objects = UserManager()
def __str__(self):
"""String for representing the Model object."""
return self.email
class Group(models.Model):
"""Model representing a Group"""
name = models.CharField(max_length=200)
members = models.ManyToManyField(settings.AUTH_USER_MODEL, through='UserGroup', related_name='user_groups')
class Meta:
ordering = ['name']
db_table = 'groups'
def __str__(self):
return self.name
class UserGroup(models.Model):
"""Model representing a User's Group"""
group = models.ForeignKey(Group, on_delete=models.CASCADE, verbose_name = 'group')
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name = 'user')
class Meta:
db_table = 'user_groups'
django.contrib.auth, provide a Group model which is not an abstract model.
When you create your CustomUser, it's inherit AbstractUser which contain a groups field, creating a many to many relation to the django.contrib.auth.Group model. So the user_groups table is created to handle the relation between CustomUser and django.contrib.auth.Group models. By default, the table name for a many to many relation concatenate table names of relation parts (_get_m2m_db_table).
In order the customize the Group model, take a look at How do I extend the Django Group model?
Related
I am trying to create nested relationship from more than two models in Django Rest Framework.
Thank you in advance for helping me.
I succeed with two models but when I'm trying with three models unable to create nested serialization.
from django.db import models
class Project(models.Model):
project_id = models.AutoField(primary_key=True)
project_name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Site(models.Model):
site_id = models.AutoField(primary_key=True)
site_name = models.CharField(max_length=255)
project_id= models.ForeignKey(Project, related_name="projectid", on_delete=models.CASCADE)
def __str__(self):
return self.site_name
class Aggin(models.Model):
assign_id = models.AutoField(primary_key=True)
site_id = Models.ForeginKey(Site, relate_name="siteid", on_delete=models.CASCADE)
from rest_framework import serializers
from .models import Song, Artist
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = ('__all__')
class SiteSerializer(serializers.ModelSerializer):
class Meta:
model = Site
fields = ('__all__')
class AggignSerializer(serializers.ModelSerializer)
class Meta:
model = Aggin
fields = ('__all__')
I think you don't need to primary id field if you wanna use the Django's default foreign key setting. And related_name should be defined from the view of the counterpart model.
from django.db import models
class Project(models.Model):
project_name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Site(models.Model):
site_name = models.CharField(max_length=255)
project = models.ForeignKey(Project, related_name="sites", on_delete=models.CASCADE)
def __str__(self):
return self.site_name
class Aggin(models.Model):
site = Models.ForeginKey(Site, relate_name="assigns", on_delete=models.CASCADE)
And then, in serializer, you can set like the following.
from rest_framework import serializers
from .models import Song, Artist
class ProjectSerializer(serializers.ModelSerializer):
sites = SiteSerializer(read_only = True, many = True)
class Meta:
model = Project
fields = ('id', 'project_name', 'sites')
class SiteSerializer(serializers.ModelSerializer):
assigns = AggignSerializer(read_only = True, many = True)
class Meta:
model = Site
fields = ('id', 'site_name', 'assigns')
class AggignSerializer(serializers.ModelSerializer):
class Meta:
model = Aggin
fields = ('id')
I have two models CustomUser and Manager_profile given below. There are 2 types of users a manager and a customer. There is a form to register as a manager. How can I set the is_manager field to True when a manager registers?
I also have another question. How can I store the data from department field to the Manager_profile model?
#Models
class CustomUser(AbstractUser):
is_manager = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
def __str__(self):
return self.first_name
class Manager_profile(models.Model):
user = models.OneToOneField(CustomUser,on_delete=models.CASCADE)
department = models.CharField(max_length=100)
def __str__(self):
return self.department
#Form
from django.contrib.auth.forms import UserCreationForm
from account.models import CustomUser
from django import forms
class ManagerCreateForm(UserCreationForm):
department = forms.CharField()
class Meta:
model = CustomUser
fields = ['username','first_name','last_name','department']
Just an fyi, I'm pretty new to programming & Django in general. I've been teaching myself.
Before I get into the problem, I'll share my Django code:
models.py :
class User(AbstractUser):
# DATABASE FIELDS
email = models.EmailField(("email address"), unique=True)
REQUIRED_FIELDS = ['username']
USERNAME_FIELD = 'email'
# META
class Meta:
verbose_name = "User"
verbose_name_plural = "Users"
# TO STRING METHOD
def __str__(self):
return "User " + str(self.id) + " - " + self.email
class UserProfile(models.Model):
# RELATIONSHIP
user = models.ForeignKey(
to = User,
on_delete = models.CASCADE,
related_name = "user_account"
)
# DATABASE FIELDS
first_name = models.CharField(max_length=100, verbose_name="First Name")
last_name = models.CharField(max_length=100, verbose_name="Last Name")
date_created = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Profile Created On")
role = models.CharField(max_length=255, verbose_name="User Demographic")
# META
class Meta:
verbose_name = "User Profile"
verbose_name_plural = "User Profiles"
# TO STRING METHOD
def __str__(self):
return self.first_name
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import User
class AbstractUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email')
class AbstractUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = UserChangeForm.Meta.fields
serializers.py
from rest_framework import serializers
from djoser.serializers import UserCreateSerializer, UserSerializer
from . import models
from .models import User, UserProfile
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = models.User
fields = ('id', 'email', 'username', 'password')
class UserCreateSerializer(UserCreateSerializer):
class Meta(UserCreateSerializer.Meta):
model = User
fields = ('id', 'email', 'username', 'password')
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ("id", "user", "first_name", "last_name", "date_created", "role")
The User(AbstractUser) model comes with some default fields. Two of those default fields I'm trying to reference are :
first_name & last_name
What I'm trying to do is, get those two default fields to connect with my UserProfile Model so that, when I create my User and fill out those fields, it will also show up in my UserProfile without having to fill it out there and connect it with a user.
Does anyone have any advice on how to achieve this connection/reference of two models?
(Just as an addition, I'm also using React for my frontend framework and have the requests working. It was just now that I realized I needed those two fields/models to connect after creating my SignUp component.)
By default, ForeignKey refers to the primary key for relation. But we can also point to other fields using to_field parameter.
I haven't tried the below code yet. But you can do something like this in your models.py:
models.py
class UserProfile(models.Model):
# RELATIONSHIP
user = models.ForeignKey(
to = User,
on_delete = models.CASCADE,
related_name = "user_account"
)
# DATABASE FIELDS
first_name = models.ForeignKey(User, to_field="firstname_field", verbose_name="First Name")
last_name = models.ForeignKey(User, to_field="lastname_field", verbose_name="Last Name")
You can refer the document here.
You need just to declare in Userprofile as OnetoOneField without declaring the first_name and last_name because User model has been declaring those field
models.py
from django.contrib.auth import get_user_model()
class UserProfile(models.model):
user = models.OnetoOneField(get_user_model(), on_delete=models.CASCADE)
I have a number of different models connected to the User model through a foregin key relationship. I would now like to display all the attributes from the objects connected to the User model in the main admin overview.
models.py
class User(AbstractBaseUser):
username = models.CharField(max_length=60)
lastname = models.CharField(max_length=60, blank=True)
class UserProfile(models.Model):
user_id = models.OneToOneField(
User,
on_delete=models.CASCADE,
primary_key=True,
)
address = models.CharField(max_length=60, blank=True)
admin.py
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('user_firstname', 'user_lastname', 'address')
def user_firstname(self, instance):
return instance.user_id.username
def user_lastname(self, instance):
return instance.user_id.lastname
admin.site.register(UserProfile, UserProfileAdmin)
The code above works perfectly well to display attributes from "User" in "Userprofile", but how do I do this the other way around? In my code I currently have 4 different objects connected to the User object so keen to find a way to display all the data there.
use inlines
models.py
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
admin.py
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
more info read https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#inlinemodeladmin-objects
I have just started learning Django Rest Framework and trying to make a simple API using Django rest Framework.
This is my models.py
from __future__ import unicode_literals
from django.db import models
class Student(models.Model):
created = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=150, blank=False)
student_id = models.CharField(max_length=20, primary_key=True)
father_name = models.CharField(max_length=150)
mother_name = models.CharField(max_length=150)
class Meta:
ordering = ('student_id',)
class Subject(models.Model):
created = models.DateTimeField(auto_now_add=True)
subject_id = models.CharField(max_length=20, primary_key=True)
name = models.CharField(max_length=150)
class Meta:
ordering = ('subject_id',)
class Result(models.Model):
created = models.DateTimeField(auto_now_add=True)
grade = models.DecimalField(max_digits=5, decimal_places=3, blank=False)
student_id = models.ForeignKey(Student, on_delete=models.CASCADE)
subject_id = models.ForeignKey(Subject, on_delete=models.CASCADE)
class Meta:
ordering = ('created',)
And this is my serializers.py
from rest_framework import serializers
from models import *
class StudentSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Student
fields = ('student_id', 'name', 'father_name', 'mother_name')
class SubjectSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Subject
fields = ('subject_id', 'name')
class ResultSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Result
fields = ('grade', 'student_id', 'subject_id')
In my "Result" model, I have two foreign keys; student_id and subject_id. This is how it looks like:
My questions is, how can I show the "name" field in the drop down menu in stead of showing "Student Object" and "Subject Object"?
I have tried with
STUDENT_CHOICES = [(each.student_id, each.name) for each in Student.objects.all()]
SUBJECT_CHOICES = [(each.subject_id, each.name) for each in Subject.objects.all()]
in the model's "choices=" field but it didn't work out.
Thanks in advance.
I think you're looking for this part of the DRF documentation.
Basically, your Django model's own representation is used. So for example, in your Student model you can add __str__ method:
# this is for Python 3, use __unicode__ on Python 2
def __str__(self):
return self.name
Meta options documentation for Django is here, look for model methods.