Can I link my customer model to my user model? - python

I'm working an a django e-commerce website where a user has to be a customer. But when I create a new user, it assigns it to the the superuser not the new user and get this error:
Exception Value: User has no customer.
But i can also go to my admin panel and re-assign the customer to the user.
django admin panel
How can I fix this please?
My customer model
class Customer(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=255, null=True)
email = models.CharField(max_length=255, null=True)
def __str__(self):
return self.name
members/views.py to create new user and customer
from django.shortcuts import render
from django.views import generic
from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from shop.models import Customer
from django.views.generic import CreateView
from .forms import CreateCustomerForm
# Create your views here.
class UserRegisterView(generic.CreateView):
form_class = UserCreationForm
template_name = 'registration/signup.html'
success_url = reverse_lazy('customer')
class CreateCustomerView(CreateView):
form_class = CreateCustomerForm
template_name = 'registration/customerProfile.html'
success_url = reverse_lazy('login')
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
My shop view
def shop(request):
data = cartData(request)
cartItems = data['cartItems']
products = Product.objects.all()
context = {'products': products, 'cartItems': cartItems}
return render(request, 'shop/shop.html', context)

The Customer model has a one-to-one unique relationship with User models.
Use contrib.auth.models.User
Example:
class Customer(models.Model):
user = models.ForeignKey(User, unique=True, related_name='customer')
Other the other hand (Slightly out of the context of the question), you can edit the User model to add the customer
from django.contrib.auth.models import User, UserManager
class CustomUser(User):
# Add the column you want o add.
# Use UserManager to get the create_user method, etc.
objects = UserManager()

Related

Django: Create a Model instance with the build-in User Model fields

So i have a Car model. And every car is submitted is assigned to a user. Also every user has his own dashboard where they can submit cars (Only for logged in users).
from django.db import models
from django.contrib.auth.models import User
class Car(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,null=True)
model_car= models.CharField(max_length=200)
description = models.TextField()
car_image = models.ImageField(null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
This is my forms.py where i create cars. And then i render this form to the frontend.
from django import forms
from django.forms import ModelForm
from tasks.models import Car
class CreateCarForm(ModelForm):
class Meta:
model=Car
fields='__all__'
exclude = ('user',)
Views.py
def create_car(request):
form = CreateCarForm()
if request.method=="POST":
form = CreateCarForm(request.POST,request.FILES)
if form.is_valid():
form.save()
messages.success(request,'Car was Created')
return redirect('create_car')
context={'form':form}
return render(request, 'dashboard/create_car.html',context)
Now it just creates a car instance, but with no selected user. What i would like to do is to create this Car instance, but in the user field, to auto assign the current logged-in user username.
How can i achieve this?
You can set the .user instance of the Car instance wrapped in the CreateCarForm:
from django.contrib.auth.decorators import login_required
#login_required
def create_car(request):
form = CreateCarForm()
if request.method=='POST':
form = CreateCarForm(request.POST,request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
messages.success(request,'Car was Created')
return redirect('create_car')
context={'form':form}
return render(request, 'dashboard/create_car.html', context)

Blog on Django, querysets for fetch logged in user's posts

I'm building a blog on Django and know i have to make a personal page for see all the posts published by the user we're logged in now.
I'm using some querysets so.
Her my code
my models.py
from django.db import models
from django.conf import settings
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
Here my forms.py
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
from .models import Post
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username','email','password1','password2','user_permissions','is_staff','date_joined']
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'text', 'author']
And that's the view which is gonna filter the posts in base of the logged user
from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from .forms import CreateUserForm
from .models import Post
from .forms import PostForm
def user_data(request, pk):
user_data = User.objects.get(pk=pk)
posts = user_data.post_set.filter(author=user_data)
context = {'user_data':user_data, 'posts':posts}
return render(request, 'account/user_data.html', context)
#So it returns me just the user data like name, email or date_joined but not his posts
This should give you posts of logged in users from your view
def user_data(request, pk):
posts=Post.objects.filter(author=request.user)
context = {'posts':posts}
return render(request, 'account/user_data.html', context)

I want to create and update UserProfile object with OneToOne User object field and create a api in Django rest framework

I'm new in Django rest framework, I tried my whole day but can't do it,I want to do full crud operation in my UserProfile Model which have a OneToOne field user, User can only update their own profile and in UserProfile create or update user shouldn't update User[username], How can i achieve it Please Help me
*** serializers.py ***
from rest_framework import serializers
from product.models import UserProfile
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
read_only_fields = ['username','password', ]
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(many=False)
class Meta:
model = UserProfile
fields = "__all__"
def create(self, validated_data):
user_data = validated_data.pop('user')
user_instance = User.objects.get(
username=user_data['username'])
user_instance.save()
user_profile_instance = UserProfile.objects.create(
**validated_data, user=user_instance)
user_profile.save()
return user_profile
*** views.py ***
from django.shortcuts import render
from .serializers import UserProfileSerializer
from rest_framework.views import APIView
from rest_framework import generics, permissions
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth.models import User
from product.models import UserProfile
# Create your views here.
class CreateUserView(generics.ListCreateAPIView):
serializer_class = UserProfileSerializer
permission_classes = [permissions.IsAuthenticated,]
def get_queryset(self):
user = self.request.user
return UserProfile.objects.filter(user = user)
*** models.py ***
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator, MinValueValidator
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='user_profile', on_delete=models.CASCADE)
country = models.CharField(max_length=50, default='India')
city = models.CharField(max_length=100, default='')
phone = models.CharField(max_length=15,default='')
image = models.ImageField(upload_to='profile_image', blank=True)
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
For Authentication you can use token based authentication(like jwt)
and for username you can use read_only=True
no need to send the password for get request
to update profile you need to handle put/post methods
CLEANED Serializers:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
read_only_fields = ['username','password']
class UserProfileSerializer(serializers.ModelSerializer):
# REMOVED all unecessary overrides
user = UserSerializer(read_only=True)
class Meta:
model = UserProfile
fields = "__all__"
Views:
class UserProfileViewSet(viewsets.GenericViewSet,
mixins.UpdateModelMixin):
# Changed inherited class and class NAME !
# I assume that your endpoint is something like /users/me/profile
# I think you want only to update user profile
# Listing or creating profile here is bad - user should have only ONE profile
# and you should do this on user model post_save signal
serializer_class = UserProfileSerializer
permission_classes = [permissions.IsAuthenticated,]
def get_object(self):
return self.request.user.user_profile
This setup will allow you to update profile and only profile data
In your models file you can make signal listener for automatically creating UserProfile object on User object create.
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)

Problem in saving extended User Model. type object 'UserProfile' has no attribute 'USERNAME_FIELD'?

I am trying to create a model UserProfile by extending it from Django's built in User model. After filling out the form the data should be saved in UserProfile model. It's just not happening
Initially, the data was only saved in User model but not in UserProfile model. I applied some recommended solutions from the web but now I cannot even fill up the form. On prompting to/register, I get an error saying,
type object 'UserProfile' has no attribute 'USERNAME_FIELD'
#models.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)
email = models.EmailField( max_length=254)
country = models.CharField( max_length=50)
#forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import UserProfile
class RegistrationForm(UserCreationForm):
class Meta:
model = UserProfile
fields = ['email', 'country']
#views.py
from django.shortcuts import render,redirect
from django.http import HttpResponse
from .forms import RegistrationForm
from .models import UserProfile
from django.contrib.auth.models import User
def home(request):
return render(request , 'guide/index.html')
def register(request):
if request.method=='POST':
form = RegistrationForm(request.POST)
if form.is_valid():
u= form.save(commit=False)
u.user = request.user
u.save()
return redirect('home')
else:
form=RegistrationForm()
return render(request, 'guide/register.html', {'form':form})
I want the code to run and save the data to UserProfile model, but the page says that UserProfile has no attribute 'USERNAME_FIELD'

How can I validate my forms or views in Django so that they can only edit the User Model only to those that belong to that data?

I have 2 models that I will allow users to edit separately, one is called User(Django default auth) and the other is UserProfile.
models.py (UserProfile)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to='avatar', default='avatar/default.png')
header = models.ImageField(upload_to='header', default='header/default.png')
bio = models.TextField(max_length=140, blank=True)
website = models.URLField(max_length=200, blank=True)
location = models.CharField(max_length=30, blank=True)
date_birth = models.DateField(null=True, blank=True)
views.py
class UserUpdateView(generic.UpdateView):
"""
This view is for editing only the User model. /edit/
"""
model = User
slug_field = 'username'
form_class = UserForm
template_name = 'user/user_edit.html'
First, use the LoginRequiredMixin mixin so that only logged-in users can access the view.
Then, override the get_object method, and return the model instance you want to edit.
You don't need the username in the URL any more, so you can remove slug_field = 'username'.
from django.contrib.auth.mixins import LoginRequiredMixin
class UserUpdateView(LoginRequiredMixin, generic.UpdateView):
model = User
form_class = UserForm
template_name = 'user/user_edit.html'
def get_object(self):
return self.request.user
If you have a similar view for editing the user profile you would return self.request.user.userprofile instead.

Categories