How to expand User(AbstractBaseUser) with OnetoOneField? - python

I want relate my Profile model with User model from class AbstractUserModel with OnetoOneFields. Is it possible? Or any solution with this problem. Here my models.py
from django.db import models
#from django.contrib.auth.models import User
from django.contrib.auth.models import (
AbstractBaseUser
)
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
class Profile(models.Model):
#HERE
user = models.OneToOneField(AbstractBaseUser, on_delete=models.CASCADE)
nama_lengkap = models.CharField(max_length=100, blank=True, null=True)
tgl_lahir = models.DateField(null=True, blank=True)
alamat = models.CharField(max_length=255)
foto_profil = models.ImageField(upload_to='foto_profil',blank=True)
jabatan = models.ForeignKey(Jabatan, on_delete=models.CASCADE)
def __str__(self):
return "{} - {}".format(self.user, self.nama_lengkap)
when I migrate this, just show some errors message like this:
SystemCheckError: System check identified some issues:
ERRORS:
users.Profile.user: (fields.E300) Field defines a relation with model 'AbstractBaseUser', which is either not installed, or is abstract.
users.Profile.user: (fields.E307) The field users.Profile.user was declared with a lazy reference to 'auth.abstractbaseuser', but app 'auth' doesn't provide model 'abstractbaseuser'.
thanks in advance

you need to replace this
user = models.OneToOneField(AbstractBaseUser, on_delete=models.CASCADE)
with
user = models.OneToOneField(User, on_delete=models.CASCADE)

However I recommend you doing it different way:
Instead of creating second User model, extend existing one:
#models.py
class ProfileUser(AbstractUser):
extra_field = models.CharField(max_length=100)
username = models.CharField(max_length=20) # modifing existing field
```
```
#settings.py
AUTH_USER_MODEL = "app_name.ProfileUser"

Related

Value Error: Cannot query "post": Must be "UserProfile" instance

I am getting the Value Error: Cannot query "post": Must be "UserProfile" instance when I make a get request to call PostListView.as_view().
Here is my model.py :
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
username = models.CharField(max_length=30)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
password = models.CharField(max_length=100)
def __str__(self):
return self.user.username
class Post(models.Model):
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
views.py :
class PostListView(ListAPIView):
serializer_class = PostSerializer
permission_classes = [AllowAny]
def get_queryset(self):
"""Returns only the object related to current user"""
user = self.request.user
return Post.objects.filter(user=user)
Also, I want a Foreign key relationship exists between User and Post on Model-level, not on the Database level.
user is UserProfile instance but request.user is a User instance
change this line like that to refernece to userprofile
user = self.request.user.userprofile

How to make a permission for checking the Model only can be update by the belonged users?

The below is my code about model Domain's Update:
serializer.py:
class DomainUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Domain
fields = "__all__"
models.py:
class Domain(models.Model):
domain_name = models.CharField(max_length=512, help_text='domain. eg.example.com')
cname = models.ForeignKey(
unique=True,
to=CNAMEModel,
on_delete=models.DO_NOTHING,
related_name="domains",
help_text="CNAME")
ssl_cert = models.TextField(max_length=40960, help_text="SSL cert + ca-bundle")
ssl_key = models.TextField(max_length=40960, help_text="SSL key")
ctime = models.DateTimeField(auto_now_add=True)
uptime = models.DateTimeField(auto_now=True)
def __str__(self):
return self.domain_name
def __unicode__(self):
return self.domain_name
class Meta:
verbose_name = "domain"
verbose_name_plural = "domain"
ordering = ['ctime']
class CNAMEModel(models.Model):
name = models.CharField(max_length=64, unique=True, help_text=". eg:gat.demo.com")
desc = models.CharField(max_length=5120, null=True, blank=True, help_text="desc")
desc_en = models.CharField(max_length=5120, null=True, blank=True")
user = models.OneToOneField(unique=True, to=AuthUser, on_delete=models.DO_NOTHING, help_text="belong user")
is_active = models.BooleanField(default=True)
ctime = models.DateTimeField(auto_now_add=True)
uptime = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def __unicode__(self):
return self.name
class Meta:
verbose_name = "CNAME"
verbose_name_plural = "CNAME"
ordering = ['ctime']
views.py:
class DomainUpdateAPIView(UpdateAPIView):
serializer_class = DomainUpdateSerializer
permission_classes = [IsAuthenticated, IsAdminUser]
queryset = Domain.objects.all()
You see Domain belong to CNAME, CNAME belong to a user.
I have a question, how can I make a permission for checking the Domain only can be update by the belonged users or AdminUser(IsAdminUser have solved)?
Or use other way rather than permission.
You can have a additional custom permission:
from rest_framework import permissions
from rest_framework.exceptions import PermissionDenied
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission to only allow creator of an object to edit it.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions are only allowed to the creator of the movie
return obj.cname.user == request.user
And in the views IsOwnerOrReadOnly can be included:
from .permissions import IsOwnerOrReadOnly
class DomainUpdateAPIView(UpdateAPIView):
serializer_class = DomainUpdateSerializer
permission_classes = [IsAuthenticated, IsAdminUser, IsOwnerOrReadOnly]
queryset = Domain.objects.all()

ForeignKey is not working django, I am using custom user model and I try both MySQL and PostgreSQL

in my SubUser model ForeignKey is not working when I add some sub user it does not get main user id to its user_id field. I try all solutions from stack overflow and I try this in both MySQL and PostgreSQL, here my codes:
dashboard/model.py
from django.db import models
from django.conf import settings
from django.contrib.auth.models import BaseUserManager
from account.models import Account
from django.contrib.auth import get_user_model
# Create your models here.
class CustomUserAdmin(BaseUserManager):
ordering = ('email',)
class SubUser(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)
image = models.ImageField(null=True, blank=True)
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
fullname = models.CharField(max_length=220)
phone_number = models.CharField(max_length=100, unique=True)
address = models.CharField(max_length=220)
user_role = models.CharField(max_length=220)
def __str__(self):
return self.fullname
dashboard/views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from . import forms
from django.conf import settings
# Create your views here.
#login_required(login_url='account:index')
def dashboard(request):
return render(request, 'dashboard/table.html')
#login_required(login_url='account:index')
def add_sub_user(request):
form = forms.AddSubUserForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.save()
print(settings.AUTH_USER_MODEL)
context = {'form':form}
return render(request, 'dashboard/add_subuser.html',context)
account/modules.py
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=220, unique=True)
fullname = models.CharField(max_length=220)
phone_number = models.CharField(max_length=220, unique=True)
address = models.CharField(max_length=220)
date_joined = models.DateTimeField(verbose_name='data 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)
username = models.CharField(max_length=220, unique=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['phone_number']
objects = MyAccountManager()
def __str__(self):
return self.fullname
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
in settings.py , I did : AUTH_USER_MODEL = 'account.Account'
Thanks in advance
I have found solution.
in dashboard/views.py I added
obj.user = request.user
now it is working

radio buttons incorrectly written to the database in django

I've a registration form, where user must chose one of 2 options.
Django renders all correctly, django admin also have it ok, but db records all possible choices as value.
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email','password1','password2']
class UserProfileForm(forms.ModelForm):
terms_compliance = forms.BooleanField(label=mark_safe('I agree with terms and conditions '))
class Meta:
model = UserProfile
widgets = {'role': forms.RadioSelect}
fields = ('role','terms_compliance')
def __init__(self):
self.fields['terms_compliance'].initial = True
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
role_choices = [('publisher','Publisher'), ('advertiser','Advertiser')]
role = models.CharField(max_length=15, choices=role_choices, default=None)
terms_compliance = models.BooleanField()
def __str__(self):
return self.user.username
In new instance (which is user.userprofile.role_choices) I need advertiser or publisher, but all I have is: [('publisher','Publisher'), ('advertiser','Advertiser')]
If you want to provide choices in a Database Field. Do like this:
class UserProfile(models.Model):
class RoleChoice(ChoiceEnum):
PUBLISHER = 'Издатель'
ADVERTISER = 'Рекламодатель'
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.CharField(max_length=15, choices=RoleChoice.choices(), default=None)
terms_compliance = models.BooleanField()
def __str__(self):
return self.user
In Views.py, populate the DB like this.
For example:
...
choice = request.query_params.get('choice') or UserProfile.RoleChoice.PUBLISHER.value
...
For more details read from here: https://django-mysql.readthedocs.io/en/latest/model_fields/enum_field.html

Cannot successfully create field 'user' for model 'userdetails': name 'UUID' is not defined

I am stuck here. Can't find the solution. I have a class in models.py:
Imports
from django.contrib.auth.models import User
from django.db import models
from django.contrib.gis.db import models
from allauth.account.models import EmailAddress
from allauth.socialaccount.models import SocialAccount
from geoposition.fields import GeopositionField
from uuid import UUID
import uuid
import hashlib
Models:
class Pincode(models.Model):
pincode = models.CharField("PinCode", max_length=6, null=False)
geom = GeopositionField("Location")
def __unicode__(self):
return u'%s' % self.pincode
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
def __unicode__(self):
return "{}'s profile".format(self.user.username)
class Meta:
db_table = 'user_profile'
def profile_image_url(self):
"""
Return the URL for the user's Facebook icon if the user is logged in via Facebook,
otherwise return the user's Gravatar URL
"""
fb_uid = SocialAccount.objects.filter(user_id=self.user.id, provider='facebook')
if len(fb_uid):
return "http://graph.facebook.com/{}/picture?width=40&height=40".format(fb_uid[0].uid)
return "http://www.gravatar.com/avatar/{}?s=40".format(
hashlib.md5(self.user.email).hexdigest())
def account_verified(self):
"""
If the user is logged in and has verified hisser email address, return True,
otherwise return False
"""
result = EmailAddress.objects.filter(email=self.user.email)
if len(result):
return result[0].verified
return False
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
class UserDetails(models.Model):
user = models.OneToOneField(User, related_name='User_Details',default= uuid.uuid4(), unique=True)
pin= models.ForeignKey(Pincode,related_name='pin', null= True, blank=True)
rating= models.CharField(max_length=12, null=True, blank=True)
def __unicode__(self):
return u'%s, %s, %s' % (self.user, self.pin, self.rating)
class Topmost(models.Model):
pincode = models.ForeignKey(Pincode, unique=True)
rating_pincode = models.CharField("Total Rating points", max_length=255, null=True, blank=True)
frequency = models.CharField("Number of user", max_length=255, null=True, blank=True)
normalized_rank = models.FloatField(null=True, blank=True)
#objects = models.GeoManager()
def __unicode__(self):
return u'%s, %s, %s' % (self.pincode, self.rating_pincode, self.frequency)
Cannot migrate it. Shows error:
ValueError: Cannot successfully create field 'user' for model 'userdetails': name 'UUID' is not defined.
On My Python IDLE:
>>> import uuid
>>> a = uuid.uuid4()
>>> type(a)
<class 'uuid.UUID'>
It shows the same error when I remove the default field too.
Any idea?
For creating OneToOne relation you shouldn't set the default value. You have to use it this way:
class UserDetails(models.Model):
user = models.OneToOneField(User, related_name='User_Details', unique=True)
rating= models.CharField(max_length=12, null=True, blank=True)
def __unicode__(self):
return u'%s' % (self.user)
Remove the uuid imports from header (both line) and try again. there is no need of uuid in this model.

Categories

Resources