I am still experiencing some problems with understanding forms and relationships between model-forms.
I am getting an error:
UserProfile.location" must be a "Location" instance.
I've set location in models to blank=True, null=True and required=False in forms.py.
And I dont really know at this point what to do with that.
How I can fix that problem?
from django.db import models
from django.contrib.auth.models import User
class Location(models.Model):
location = models.CharField(max_length=32)
#county = models.CharField(max_length=32)
#province = models.CharField(max_length=32)
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True, primary_key=True)
location = models.ForeignKey("Location", null=True, blank=True)
website = models.URLField("Site", null=True, blank=True)
accepted_rules = models.BooleanField(default=False)
accepted_rules_date = models.DateTimeField(auto_now_add=True)
#points_count = models.IntegerField(default=0, null=True, blank=True)
#posts_count = models.IntegerField(default=0, null=True, blank=True)
#comments_count = models.IntegerField(default=0, null=True, blank=True)
Forms:
from django import forms
from django.forms import Form
from django.forms.models import ModelForm
from accounts.models import UserProfile, Location
from django.contrib.auth.models import User
class UserCreationForm(forms.Form):
username = forms.CharField(max_length=32)
password = forms.CharField(widget=forms.PasswordInput())
email = forms.EmailField()
#password_repeat = forms.CharField(widget=forms.PasswordInput(render_value=False))
def clean_username(self):
try:
# iexact = case-insensitive match / important for validation
User.objects.get(username__iexact=self.cleaned_data['username'])
print "User does already exist"
except User.DoesNotExist:
return self.cleaned_data['username']
else:
raise forms.ValidationError("User already exists")
def clean_email(self):
if User.objects.filter(email__iexact=self.cleaned_data['email']):
print u'Adres email jest już używany.'
raise forms.ValidationError('Adres email jest już używany.')
else:
return self.cleaned_data['email']
def save(self):
user = User.objects.create(username = self.cleaned_data['username'], email = self.cleaned_data['email'],)
user.set_password(self.cleaned_data['password'])
return user
class UserProfileForm(ModelForm):
website = forms.URLField(label="website", required=False)
location = forms.ChoiceField(required=False)
class Meta:
model = UserProfile
include = ['website', 'location']
exclude = ('user', 'type', 'accepted_rules')
Views
contrib.auth.models import User
from django.template.response import TemplateResponse
from django.views.decorators.csrf import csrf_protect
from django.core.context_processors import csrf
from django.forms.models import inlineformset_factory
from django.http import HttpResponseRedirect
from accounts.forms import UserCreationForm, UserProfileForm
def index(request):
return TemplateResponse(request, "base.html")
#csrf_protect
def register(request):
form = UserCreationForm()
user_profile = UserProfileForm()
if request.method == "POST":
form = UserCreationForm(prefix='user', data=request.POST or None)
user_profile = UserProfileForm(prefix='profile', data= request.POST or None)
if form.is_valid() and user_profile.is_valid():
user = form.save()
profile = user_profile.save(commit=False)
profile.user = user
profile.save()
return HttpResponseRedirect("/")
return TemplateResponse(request, 'accounts/register.html', {
'form':form,
'user_profile':user_profile ,
}
)
The problem is here.
class UserProfileForm(ModelForm):
website = forms.URLField(label="website", required=False)
location = forms.ChoiceField(required=False)
class Meta:
model = UserProfile
include = ['website', 'location']
exclude = ('user', 'type', 'accepted_rules')
ModelForm will generate needed fields for your form. You don't need to define them manually. So you should use something like this.
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
include = ['website', 'location']
exclude = ('user', 'type', 'accepted_rules')
Another thing. There is no include option, I think you wanted to use fields. But you don't have to use both fields and exclude, usually you need to use one them. In your case exclude is enough. Final result:
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
exclude = ('user', 'type', 'accepted_rules')
Related
When I run my code I keep getting this error " 'User' object has no attribute 'products' 'User' " I don't know where I went wrong please help me. Below is are my user's app codes
Because I am trying to build the website to display products onto the user's profile page so the user can see the products they have got and also display these products on the main home page but I got stuck with this error. "'User' object has no attribute 'products'"
**View.py**
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'{username}! your account created')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
#login_required
def profile(request):
users = request.user
products = users.products.all()
return render(request, 'users/profile.html', {'user': users, 'products': products})
#login_required
def add_product(request):
if request.method == 'POST':
form = ProductForm(request.POST, request.FILES)
if form.is_valid():
product = form.save(commit=False)
product.users = request.user
product.slug = slugify(product.title)
product.save()
return redirect('profile')
else:
form = ProductForm()
return render(request, 'users/add_product.html', {'form': form})
Models.py
from django.contrib.auth.models import User
from django.db import models
class Users(models.Model):
name = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.OneToOneField(User, related_name='users', on_delete=models.CASCADE)
class Meta:
ordering = ['name']
def __str__(self):
return self.name
forms.py
This is my forms.py file in my users app
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.forms import ModelForm
from product.models import Product
class UserRegisterForm(UserCreationForm):
first_name = forms.CharField(max_length=40)
last_name = forms.CharField(max_length=40)
username = forms.CharField(max_length=40)
address = forms.CharField(max_length=300)
postcode = forms.CharField(max_length=10)
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'address', 'postcode', 'password1', 'password2']
class ProductForm(ModelForm):
class Meta:
model = Product
fields = ['category', 'image', 'title', 'description', 'price']
Product model
This is the product model in my product app
from io import BytesIO
from PIL import Image
from django.core.files import File
from django.db import models
from users.models import Users
class Category(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
ordering = models.IntegerField(default=0)
class Meta:
ordering = ['ordering']
def __str__(self):
return self.title
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
vendor = models.ForeignKey(Users, related_name='products', on_delete=models.CASCADE)
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
date_added = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='uploads/', blank=True, null=True)
thumbnail = models.ImageField(upload_to='uploads/', blank=True, null=True)
class Meta:
ordering = ['-date_added']
def __str__(self):
return self.title
def get_thumbnail(self):
if self.thumbnail:
return self.thumbnail.url
else:
if self.image:
self.thumbnail = self.make_thumbnail(self.image)
self.save()
return self.thumbnail.url
else:
return 'https://via.placeholder.com/240x180.jpg'
def make_thumbnail(self, image, size=(300, 200)):
img = Image.open(image)
img.convert('RGB')
img.thumbnail(size)
thumb_io = BytesIO()
img.save(thumb_io, 'JPEG', quality=85)
thumbnail = File(thumb_io, name=image.name)
return thumbnail
I want to implement update User Profile,in django rest framework.
I am getting the above mentioned error, no matter what I try and change in my code.
Below is the the code for my user serializers, user model and api views.
users/api/serializers.py:
from rest_framework import serializers
from ..models import User,Profile
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username','first_name','last_name','phone','id')
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = Profile
fields = ('user', 'bio', 'image')
def update(self,instance,validated_data):
user_data = validated_data.pop('user',{})
user = instance.user
instance.bio = validated_data.get('bio',instance.bio)
instance.image = validated_data.get('image',instance.image)
instance.save()
return instance
Is there anything wrong in my serializer, cause I tried hardcoding and saving a particular user profile also by using for ex: instance.user.id = 21 and then saving it, but i get the same error
Is there anything wrong in my serializer, cause I tried hardcoding and saving a particular user profile also by using for ex: instance.user.id = 21 and then saving it, but i get the same error
users/models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.conf import settings
import os
import random
import string
class MyAccountManager(BaseUserManager):
def create_user(self,phone,username,first_name,last_name):
if not phone:
raise ValueError("Users must have a valid phone number")
if not username:
raise ValueError("Users must have a valid username")
if not first_name:
raise ValueError("Users must have a valid First Name")
if not last_name:
raise ValueError("Users must have a valid last name")
user = self.model(
phone=phone,
username=username,
first_name=first_name,
last_name=last_name
)
user.save(using=self._db)
return user
def create_superuser(self,username,phone,first_name,last_name,password = None):
user = self.create_user(
username=username,
phone=phone,
first_name=first_name,
last_name=last_name,
)
user.set_password(password)
user.is_admin=True
user.is_staff=True
user.is_superuser=True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
phone = models.CharField(unique=True,max_length=20)
username = models.CharField(max_length=50,unique=True)
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=30, blank=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)
otp = models.CharField(max_length=10,default='')
USERNAME_FIELD = 'phone'
REQUIRED_FIELDS = ['username','first_name','last_name']
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
class Profile(models.Model):
user = models.OneToOneField(User,on_delete = models.CASCADE)
bio = models.CharField(max_length=140)
image = models.ImageField(default='default.jpg',upload_to='profile_pics')
def __str__(self):
return f'{self.user.username}'
users/api/views.py
from rest_framework import status
from rest_framework.response import Response
from rest_framework import viewsets
from rest_framework.views import APIView
from .serializers import UserSerializer,UserProfileSerializer
from ..models import User,Profile
from django_filters.rest_framework import DjangoFilterBackend
class ProfileViewset(viewsets.ModelViewSet):
model = Profile
serializer_class = UserProfileSerializer
queryset = Profile.objects.all()
filter_backends = [DjangoFilterBackend]
filterset_fields = ['user']
Please add null=True if you want to insert null value.This is my suggestion
class Profile(models.Model):
user = models.OneToOneField(User,null=True,on_delete = models.CASCADE)
bio = models.CharField(max_length=140)
image = models.ImageField(default='default.jpg',upload_to='profile_pics')
def __str__(self):
return f'{self.user.username}'
I'm using a ModelForm in Django but some fields are not saved to the database...
models.py file
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.forms import ModelForm
# Create your models here.
class Bill(models.Model):
image_name = models.CharField(max_length=150)
upload_date = models.DateTimeField(default=timezone.now)
image = models.ImageField()
description = models.TextField(blank=True)
result = models.CharField(max_length=1000)
uploaded_by = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
def __str__(self):
return str(self.result + self.description)
forms.py file
from django import forms
from django.db import models
from django.forms import ModelForm
from .models import Bill
class BillForm(ModelForm):
class Meta:
model = Bill
fields = ['image', 'description']
exclude = ['result', 'image_name', 'upload_date', 'uploaded_by']
views.py file
def upload(request):
if request.method == 'POST':
form = BillForm(request.POST, request.FILES)
if form.is_valid():
form.image_name = request.FILES['image']
form.upload_date = datetime.now()
form.uploaded_by = request.user
form.result = "something"
form.save()
return redirect('cism-home')
else:
form = BillForm()
return render(request, 'auth/upload.html', {'form': form})
So the image and description fields are saved but other fields are not. Any ideas why is that?
Your form is excluding some fields, so you can't "access" those fields using:
form.upload_date (for example), because they don't exists.
What you can do is:
if form.is_valid():
bill = form.save(commit=False)
bill.image_name = request.FILES['image']
bill.upload_date = datetime.now()
bill.uploaded_by = request.user
bill.result = "something"
bill.save()
If you want a quick description about what "commit=False" do, you can check:
Django ModelForm: What is save(commit=False) used for?
I am trying to create a registration form (using Django ModelForm) where I want to validate if the 'password' and confirm password match. I tried using the raise ValidationError but I get an error saying
type object 'ModelForm' has no attribute 'ValidationError'
What should be the correct way to validate the passwords? Here's my code below:
models.py:
from django.db import models
class Students(models.Model):
firstName = models.CharField(max_length=120)
lastName = models.CharField(max_length=120)
# studentID = models.IntegerField(null=False)
email = models.EmailField()
password = models.CharField(max_length=120, default="")
password2 = models.CharField(max_length=120, default="")
street = models.CharField(max_length=120)
apt = models.IntegerField(blank=True, null=True)
city = models.CharField(max_length=120)
state = models.CharField(max_length=120)
zipcode = models.IntegerField(null=False)
def __str__(self):
return self.firstName
class Meta:
verbose_name_plural = "Students"
forms.py:
from django.forms import ModelForm
from django.utils.translation import gettext_lazy as _
from .models import Students
class StudentRegisterForm(ModelForm):
class Meta:
model = Students
fields = [
'firstName', 'lastName',
'email', 'password', 'password2',
'street', 'apt', 'city', 'state', 'zipcode',
]
labels = {
'firstName': _('First Name'),
'lastName': _('Last Name'),
'password2': _('Confirm Password'),
'Apt': _('Apt/House'),
'zipcode': _('Zip Code'),
}
def clean(self):
data = self.cleaned_data
password = self.cleaned_data.get('password')
print(password)
password2 = self.cleaned_data.get('password2')
if password2 != password:
raise ModelForm.ValidationError("Passwords must match!")
return data
Views.py:
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .models import Students
from .forms import StudentRegisterForm
def student_register(request):
register_form = StudentRegisterForm(request.POST or None)
context = {
"title": "Welcome to the registration page",
"register_form": register_form
}
if register_form.is_valid():
register_form.save()
return render(request, 'students/register.html', context)
I'm pretty new to programming so please try to explain where I am going wrong and what the correct approach is. Thanks!
ValidationError is not an attribute of ModelForm.
from django.forms import ModelForm, ValidationError
....
raise ValidationError("Passwords must match!")
or, better:
from django import forms
class StudentRegisterForm(forms.ModelForm):
...
raise forms.ValidationError("Passwords must match!")
How to Save Data from Serializer to Model Database. Following is an example Code but Not Saving Data to Database!
For Example I am using a Sample Example View:
views.py
#api_view(['GET', 'POST', ])
def login(request):
if request.method == "POST":
s = LoginSerializer(data=request.data)
if s.is_valid():
s.save()
return Response(s.data, status=201)
else:
return Response(s.data, status=203)
else:
return Response("", status=404)
models.py
from django.db.models import Model
from django.db import models
class UserDetails(Model):
userid = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
phone = models.CharField(max_length=15)
class UserLogin(Model):
userid = models.ForeignKey(UserDetails, on_delete=None)
email = models.CharField(max_length=20)
password = models.CharField(max_length=30)
serializers.py
from rest_framework import serializers
from api.models import UserLogin, UserDetails
class LoginSerializer(serializers.Serializer):
userid = serializers.Field()
email = serializers.EmailField()
password = serializers.CharField(max_length=20)
def create(self, validated_data):
return UserLogin.objects.create(**validated_data)
serializers.py
from rest_framework import serializers
from api.models import UserLogin, UserDetails
class LoginSerializer(serializers.Serializer):
userid = serializers.Field()
email = serializers.EmailField()
password = serializers.CharField(max_length=20)
def create(self, validated_data):
return super().create(validated_data)