Auto added primary key trying to insert the value of NULL - sql-server

I have a Django site, and am using windows auth for it. When I try to logon as a new user it gives the error Cannot insert the value NULL into column 'id', table 'table.auth_user'; column does not allow nulls. INSERT fails. One other thing to mention is that that I have a separate db for my Auth (but the AuthDB is the default one).
models.py
class AuthUser(models.Model):
password = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)
is_superuser = models.BooleanField()
username = models.CharField(unique=True, max_length=150)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=150)
email = models.CharField(max_length=254)
is_staff = models.BooleanField()
is_active = models.BooleanField()
date_joined = models.DateTimeField()
class Meta:
managed = False
db_table = 'auth_user'
def __str__(self):
return self.username
In settings.py
DATABASES = {
'default': {
'ENGINE': 'sql_server.pyodbc',
'NAME': 'AuthDB',
'HOST': 'MyHost',
'USER': '',
'PASSWORD': '',
'OPTIONS': {
'driver':"ODBC Driver 13 for SQL Server",
},
'CONN_MAX_AGE': 60,
},
I am not sure why django is trying to insert the value of NULL into the the auto added primary key id. Maybe I am missing something? Does anyone have any idea why?
Thanks for the help!

Related

I am getting null value in column "user_id" violates not-null constraint, how can I get foreign key data to register on my comment form?

This my models.py file
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
class UserAccountManager(BaseUserManager):
def create_user(self, name, email, password, **other_fields):
if not email:
raise ValueError('Users must have an email adress')
email = self.normalize_email(email)
user = self.model(name=name, email=email, password=password)
user.set_password(password)
user.save()
return user
def create_superuser(self, name, email, password = None, **other_fields):
other_fields.setdefault('is_staff', True)
other_fields.setdefault('is_superuser', True)
other_fields.setdefault('is_active', True)
return self.create_user(name=name, email=email, password = password, is_superuser=True)
class UserAccount(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=355, unique=False)
is_superuser = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
objects = UserAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def __str__(self):
return str(self.id)
I have a foreign key on my comment model, I tested this on django admin and it works fine, but with my comment form, the foreign key isn't populating, i just get "null value in column "user_id" violates not-null constraint", I dont know what im doing wrong
class Comment(models.Model):
comment = models.CharField(max_length=250)
user = models.ForeignKey(UserAccount, on_delete=models.CASCADE)
def __str__(self):
return str(self.user.id)
serializers.py
from djoser.serializers import UserCreateSerializer
from django.contrib.auth import get_user_model
from rest_framework.serializers import ModelSerializer
from accounts.models import Comment
User = get_user_model()
class UserCreateSerializer(UserCreateSerializer):
class Meta(UserCreateSerializer.Meta):
model = User
fields = ('id', 'name', 'email', 'password')
I am reffering my foreign key user as a field, i'm not sure if that is correct.
class CommentSerializer(ModelSerializer):
class Meta:
model = Comment
fields=('id', 'comment', 'user')
viewsets.py
from rest_framework import viewsets
from . import models
from . import serializers
class CommentViewset(viewsets.ModelViewSet):
queryset = models.Comment.objects.all()
serializer_class = serializers.CommentSerializer
router.py
from accounts.viewsets import CommentViewset
from rest_framework import routers
router = routers.DefaultRouter()
router.register('comment', CommentViewset)
You need to add user_id field for writing in the serializer.
class CommentSerializer(ModelSerializer):
class Meta:
model = Comment
fields=('id', 'comment', 'user')
extra_kwargs = {
'user': { 'read_only': True }
}
def create(self, validated_data):
new_comment = Comment(**validated_data)
new_comment.user_id = self.context['request'].user.id
new_comment.save()
return new_comment

Identify the custom user model in REST_FRAMEWORK settings Django

I'm new in Django rest_framework. I'm using a custom user model and djoser as my authentication system. I want to use my custom user model in the djoser register view and I don't know how to identify that in the rest_framework settings?
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSIONS_CLASSES':(
'rest_framework.permissions.IsAuthenticated',
),
}
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, phone, password=None):
if not email:
raise ValueError("Users must have an email address")
if not username:
raise ValueError("Users must have an username")
if not phone:
raise ValueError("Users must have a phone number")
user = self.model(
email=self.normalize_email(email),
username=username,
phone=phone
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self,email, username, phone, password):
user = self.create_user(
email=self.normalize_email(email),
username=username,
phone=phone,
password=password
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email",max_length=60, unique=True)
username = models.CharField(max_length=60,unique=True)
phone = models.CharField(max_length=60,unique=True)
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)
first_name = models.CharField(max_length=60,null=True)
last_name = models.CharField(max_length=60,null=True)
wilaya = models.CharField(max_length=60,null=True)
city = models.CharField(max_length=60,null=True)
address = models.CharField(max_length=200,null=True)
store_coordinates = models.CharField(max_length=60,null=True)
documents1 = models.CharField(max_length=60,null=True)
documents2 = models.CharField(max_length=60,null=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email','phone']
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
What should I add to use my custom user model in djoser register view?
You're doing almost everything right, but you need to tell Django in the settings what user model it should use.
In models.py use something like this
from django.contrib.auth.models import AbstractUser
from .managers import UserManager
class User(AbstractUser):
# Add whatever fields you want
# Use your custom manager
objects = UserManager()
In settings.py
# Tell Django what user model should be used
AUTH_USER_MODEL = 'auth.User' # app_label.model
make sure you use python manage.py makemigrations && python manage.py migrate to create your custom user model.
Enjoy!

'Account' object has no attribute 'products' AND (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.'

I am following Django rest_framework tutorial to build my app but and I'm using a custom user model (Account) which inherits AbstractBaseUser.
I have another model - Product - and each product is owned by an Account.
My models.py is:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.conf import settings
class Product(models.Model):
owner = models.ForeignKey(Account, related_name='account', on_delete=models.CASCADE, default=1)
name = models.CharField(max_length=71)
product = models.CharField(max_length=20, blank=True)
price = models.IntegerField(null=True, blank=True)
quantity = models.IntegerField(default=0)
image = models.ImageField(upload_to='images', blank=True)
display = models.BooleanField(default=False)
created = models.DateTimeField('date added', auto_now=True)
modified = models.DateTimeField('date modified', auto_now_add=True)
def __str__(self):
return self.name
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError("Please enter a valid email address")
if not username:
raise ValueError("Please enter a username")
user = self.model(
email = self.normalize_email(email),
username = username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email = self.normalize_email(email),
password = password,
username = username,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last_login', auto_now_add=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)
is_merchant = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = MyAccountManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
My settings.py includes:
AUTH_USER_MODEL = 'accounts.Account'
My serializers.py is:
from rest_framework import serializers
from inventory.models import Product
from accounts.models import Account
class AccountSerializer(serializers.ModelSerializer):
products = serializers.PrimaryKeyRelatedField(many=True, queryset=Product.objects.all())
password2 = serializers.CharField(style={'input_type': 'password'}, write_only=True)
class Meta:
model = Account
fields = ['products', 'email', 'username', 'password', 'password2']
extra_kwargs = {
'password': {'write_only': True}
}
def save(self):
account = Account(
email = self.validated_data['email'],
username = self.validated_data['username'],
)
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password': 'Passwordss must match.'})
account.set_password(password)
account.save()
return account
class ProductSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.email')
class Meta:
model = Product
fields = [
'id', 'owner', 'name', 'product', 'price', 'quantity', 'image', 'display'
]
My views.py is:
from accounts.api.serializers import AccountSerializer
from inventory.api.serializers import ProductSerializer
from inventory.models import Product
from accounts.models import Account
from rest_framework import permissions
from rest_framework import generics
class AccountList(generics.ListAPIView):
queryset = Account.objects.all()
serializer_class = AccountSerializer
class AccountDetail(generics.RetrieveAPIView):
queryset = Account.objects.all()
serializer_class = AccountSerializer
class ProductList(generics.ListCreateAPIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
queryset = Product.objects.all()
serializer_class = ProductSerializer
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class ProductDetail(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
queryset = Product.objects.all()
serializer_class = ProductSerializer
I am able to view my ProductList and ProductDetail however, I get the following error when I try to view AccountList and AccountDetail:
**Exception Type:** AttributeError
**Exception Value:** 'Account' object has no attribute 'products'
Just change your serailzier like this
class AccountSerializer(serializers.ModelSerializer):
products = serializers.SerializerMethodField()
password2 = serializers.CharField(style={'input_type': 'password'}, write_only=True)
def get_products(self, instance):
return Product.objects.all().values_list('id', flat=True)
class Meta:
model = Account
fields = ['products', 'email', 'username', 'password', 'password2']
extra_kwargs = {
'password': {'write_only': True}
}
def save(self):
account = Account(
email = self.validated_data['email'],
username = self.validated_data['username'],
)
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password': 'Passwordss must match.'})
account.set_password(password)
account.save()
return account
PrimaryKeyRelatedField may be used to represent the target of the relationship using its primary key. The queryset used for model instance lookups when validating the field input. Your field is read_only field. Your should use SerializerMethodField for this.

Django migration doesn't contain composite foreign key relationship and composite primarykey with MSSQL database

I just start new Django project with existing MSSQL (not mysql) database. In database I have four table which all are in relationship with together. I build the model for existing table bypython manage.py inspectdb (table _name). but it doesn’t gives any relation neither foreign key nor OneToOne. So I update the models.py as per table relationship.
Note that each table has composite primary key and composite foreign key. I define composite primary key with unique_togather=() and for composite foreign key by using Django third party library
Django-composite-foreignkey module.
But when I tried to migrate .it doesn’t seem to establish the relationship
models.py
from django.db import models
from compositefk.fields import CompositeForeignKey, CompositeOneToOneField
class Company(models.Model):
code = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)
srccode = models.SmallIntegerField(db_column='SrcCode')
est = models.DateTimeField(db_column='Est')
rownum = models.BigIntegerField(db_column='RowNum')
class Meta:
manage = False
unique_together = ('code', 'srccode')
db_table = 'Company'
class Department(models.Model):
depcode = models.DecimalField(db_column='DepCode', max_digits=38, decimal_places=0)
depsrccode = models.SmallIntegerField(db_column='Depsrccode')
name = models.CharField(db_column='Name')
rownum = models.BigIntegerField(db_column='RowNum')
class Meta:
manage = False
unique_together = ('depcode', 'depsrccode')
db_table = 'department'
class Floor(models.Model):
code = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)
srccode = models.SmallIntegerField(db_column='SrcCode')
depcode = models.DecimalField(db_column='DepCode', max_digits=38, decimal_places=0)
depsrccode = models.SmallIntegerField(db_column='Depsrccode')
floorname = models.CharField(db_column='FloorName')
rownum = models.BigIntegerField(db_column='RowNum')
company = CompositeForeignKey(Company,on_delete=models.CASCADE,to_fields={'code':'code','srccode': 'srccode'})
department= CompositeOneToOneField(Department,on_delete=models.CASCADE,to_fields={'depcode':'depcode','depsrccode': 'depsrccode'})
class Meta:
manage = False
unique_together = ('depcode', 'depsrccode','floorname')
db_table = 'floor'
class SubCompany(models.Model):
code = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)
srccode = models.SmallIntegerField(db_column='SrcCode')
subname = models.CharField(db_column='SubName')
rownum = models.BigIntegerField(db_column='RowNum')
company = CompositeForeignKey(Company,on_delete=models.CASCADE,to_fields={'code':'code','srccode': 'srccode'})
class Meta:
manage = False
unique_together = ('code', 'srccode','subname','rownum')
db_table = 'SubCompany'
I add all composite foreign and primary key constrain after auto create models from inspectdb.
My initial migration file as per below
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='SubCompany',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code' = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)),
('srccode' = models.SmallIntegerField(db_column='SrcCode')),
('subname' = models.CharField(db_column='SubName')),
('rownum' = models.BigIntegerField(db_column='RowNum')),
],
options={
'db_table': 'SubCompany',
'managed': False,
},
),
migrations.CreateModel(
name='Company',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code' = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)),
('srccode' = models.SmallIntegerField(db_column='SrcCode')),
('est' = models.DateTimeField(db_column='est')),
('rownum' = models.BigIntegerField(db_column='RowNum')),
],
options={
'db_table': 'Company',
'managed': False,
},
),
migrations.CreateModel(
name='Floor',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code' = models.DecimalField(db_column='Code', max_digits=38, decimal_places=0)),
('srccode' = models.SmallIntegerField(db_column='SrcCode')),
('depcode' = models.DecimalField(db_column='DepCode', max_digits=38, decimal_places=0)),
('depsrccode' = models.SmallIntegerField(db_column='DepSrcCode')),
('name' = models.CharField(db_column='Name')),
('rownum' = models.BigIntegerField(db_column='RowNum')),
],
options={
'db_table': 'Floor',
'managed': False,
},
),
migrations.CreateModel(
name='Department',
fields=[
('depcode' = models.DecimalField(db_column='DepCode', max_digits=38, decimal_places=0)),
('depsrccode' = models.SmallIntegerField(db_column='DepSrcCode')),
('name' = models.CharField(db_column='Name')),
('rownum' = models.BigIntegerField(db_column='RowNum')),
],
options={
'db_table': 'Department',
'managed': False,
},
),
]
Why in migration file doesn’t have all relationship and primary key constrain.? Is there anything that I am missing.? how can i build the models as per my table relations? Any help much appreciate.
requirements.txt
Django==2.1.7
django-composite-foreignkey==1.1.0
django-crispy-forms==1.7.2
django-extensions==2.1.6
django-filter==2.1.0
django-mssql==1.8
django-pyodbc-azure==2.1.0.0
djangorestframework==3.9.2
graphviz==0.10.1
Markdown==3.0.1
pydotplus==2.0.2
pyodbc==4.0.26
pyparsing==2.3.1
pytz==2018.9
pywin32==224
six==1.12.0
The short answer is that Django does not support composite primary keys/Index combos like entity framework does. Since it's not natively supported and it appears to be a business requirement, I might suggest using another ORM framework. If you're bound to Django, you can read more here:
https://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys
You have to write like this tuple inside tuple because of multiple row will be composite pk.
class Meta:
manage = False
unique_together = (('depcode', 'depsrccode'),)
db_table = 'department'

How to add custom user field (phone_number) in django default user table?

I need to add a custom field called phone_number to the default django user table
Everything work fine but the phone_number field and value does not save in Table Django User.
Here is my custom form code
class SignUpForm(UserCreationForm):
username = forms.EmailField(label="Email Address", max_length=254, help_text='Required a valid email address.')
phone_number = forms.CharField(max_length=30, help_text='Required.')
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'phone_number', 'password1', 'password2')
Here is my view code for user registration
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
mail_subject = 'Activate Your Account.'
message = render_to_string('app/account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'token': account_activation_token.make_token(user),
})
to_email = form.cleaned_data.get('username')
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
return render(request, 'app/account_confirm_message.html')
else:
form = SignUpForm()
return render(request, 'app/signup.html', {'form': form})
My Model is here
class Profile(models.Model):
STUDENT = 1
TEACHER = 2
ROLE_CHOICES = (
(STUDENT, 'Student'),
(TEACHER, 'Teacher'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
email_confirmed = models.BooleanField(default=False)
role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True)
# this method called for admin panel
class Meta:
verbose_name = 'profile'
verbose_name_plural = 'profiles'
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()

Resources