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
Related
I'm working on a blog where i can allow other user upload/post content
Now I'm working on the frontend user post where user can publish their post all fields are working except the image field
after inputting the necessary detail it will show me this ''ValueError: The 'image' attribute has no file associated with it.''
Please how can i fix this
my code below
views.py
if request.method == 'POST':
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
form.save()
else:
print(form.errors)
# else:
# form = ArticleForm()
return render(request, 'CreatePost.html', {'form': form})
forms.py
from django import forms
from . models import Article
class ArticleForm(forms.ModelForm):
# image = forms.ImageField(**kwargs, upload_to='featured_image/%Y/%m/%d/') #this
class Meta:
model = Article
fields = [
'title',
'image',
'slug',
'author',
'body',
'publish',
'status'
]
models.py
# models
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager,self).get_queryset().filter(status='published')
# post model
class Article(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
image = models.ImageField(upload_to='featured_image/%Y/%m/%d/') #this
slug = models.SlugField(max_length=250, unique_for_date='publish')
author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='blog_posts')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,choices=STATUS_CHOICES,default='draft')
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
objects = models.Manager() # The default manager.
published = PublishedManager() # Our custom manager.
def get_absolute_url(self):
return reverse('Blog:post',args=[self.slug])
I can Imagine, what you don't set in form html Tag the enctype= "multipart/form-data"
More Here:
https://docs.djangoproject.com/en/4.0/ref/forms/api/#binding-uploaded-files-to-a-form
i have a an order model which is in m2m relationship with a product model, when i create an order, and after checking my DB, i can see the order saved but not in the through model
models.py
from inventory.models import Product
from user.models import User
class Order(models.Model):
product = models.ManyToManyField(Product, through='OrderItems' )
vendeur = models.ForeignKey(User, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
class Customer(models.Model):
full_name = models.CharField(max_length=60, verbose_name='full name')
address = models.CharField(max_length=255)
phone = models.CharField(max_length=20)
city = models.CharField(max_length=30)
class OrderItems(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order,on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
views.py
#login_required
def add_order(request):
if request.method == 'POST':
form = NewOrderForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
order.vendeur = request.user
order.save()
return redirect('dashboard-index', )
else :
form = NewOrderForm()
return render(request, 'dashboard/add_order.html', {'form': form})
forms.py
class NewOrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ('product','quantity')
if you use save(commit=False), Calling save_m2m() is required.
because your form has a m2m field
refer to documentions
#login_required
def add_order(request):
if request.method == 'POST':
form = NewOrderForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
order.vendeur = request.user
order.save()
form.save_m2m()
return redirect('dashboard-index', )
else :
form = NewOrderForm()
return render(request, 'dashboard/add_order.html', {'form': form})
I have model from which I created a ModelForm:
models.py:
class City(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return f'{self.name}'
class Profile(models.Profile):
name = models.CharField(max_length=50)
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=False)
location = models.ForeignKey('City', on_delete=models.SET_NULL, blank=True, null=True)
forms.py
from django import forms
from .models import Profile, City
class LocationField(forms.CharField):
def clean(self, value):
try:
city = City.objects.get(name=value)
except ObjectDoesNotExist:
city = City.objects.create(name=value)
return city
class ProfileForm(forms.ModelForm):
location = LocationField()
class Meta:
model = Profile
exclude = ['user']
views.py
def profile_update_view(request):
template_name = 'profiles/update.html'
user = request.user
profile = Profile.objects.get(user__id=user.id)
if request.method == 'GET':
form = ProfileForm(instance=profile)
else:
form = ProfileForm(request.POST, instance=profile)
if form.is_valid():
obj = form.save(commit=False)
obj.user = user
obj.save()
return redirect('profile_view')
context = {'form': form}
return render(request, template_name, context=context)
When I'm saving form, I'm satisfied how it's working, but when I load form again to update in, it fills LocationField() as an City pk integer, but I want it to load name instead. Is there a way to do this?
I've added in views.py:
if request.method == 'GET':
initial = {}
if profile.location:
initial = {'location': profile.location.name}
form = ProfileForm(instance=profile, initial=initial)
now it's working. But it's some workaround. I've thought there is some parameter maybe
While rendering the form in web browser, the dropdown menu of CPA_Clients should be empty since I've used "self.fields['name'].queryset = CPA_Client.objects.none()" (Since I'll be making it chained dropdown) in forms.py file, but I still see all the contents of CPA_Clients in dropdown.
Where did I go wrong?
forms.py
from django import forms
from .models import Task, CPA_Client
class TaskDetails(forms.Form):
class Meta:
model = Task
fields = '__all__'
def __init__(self, *args, **kwargs):
super(TaskDetails, self).__init__(*args, **kwargs)
self.fields['name'].queryset = CPA_Client.objects.none()
models.py
from django.db import models
from django.contrib.auth.models import User
from datetime import datetime
from uuid import uuid4
from django.urls import reverse
import os
#Create your models here.
class TaskType(models.Model):
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = 'Task Type'
class CPAsList(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = 'CPAs'
class CPA_Client(models.Model):
CPA = models.ForeignKey(CPAsList,on_delete=models.CASCADE, null=True)
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = 'CPA\'s Clients'
def get_random_filename(instance, filename):
now = datetime.now()
path = now.strftime("%Y/%B/%d")
instance.filename = filename
ext = filename.split('.')[-1]
filename = "%s.%s" % (str(uuid4()), ext)
return os.path.join(path, filename)
TASK_STAGE = [
('NE','New'),
('OG','Ongoing'),
('CM','Completed')
]
PRIORITY = [
('HI','High'),
('ME','Medium'),
('LO','Low')
]
class Document(models.Model):
file = models.FileField(upload_to=get_random_filename, default="")
filename = models.CharField(max_length=128, editable=False, default="")
def __str__(self):
return self.filename
class Task(models.Model):
Stage = models.CharField(max_length=100, choices=TASK_STAGE, default='NE')
Subject_Line = models.CharField(max_length=255, default="", editable=True,)
Task_Type = models.ForeignKey(TaskType, on_delete=models.SET_NULL, null=True)
CPA = models.ForeignKey(CPAsList, on_delete=models.SET_NULL, null=True)
Client_of_CPA = models.ForeignKey(CPA_Client, on_delete=models.SET_NULL, null=True)
Priority = models.CharField(max_length=100, choices = PRIORITY, default='ME')
Assign_to = models.ForeignKey(User, on_delete=models.CASCADE, related_name='assignedUser')
Date_Added = models.DateTimeField(editable=True, null=True, default=datetime.now)
Additional_Note = models.TextField(blank=True, null=True)
Author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='assigneeUser', null=True, editable=False)
def __str__(self):
return self.Subject_Line
def get_absolute_url(self):
return reverse('task-detail', kwargs={'pk': self.pk})
class TimeStamps(models.Model):
Task_ID = models.ForeignKey(User, on_delete=models.CASCADE)
TimeStamp = models.IntegerField(default=0)
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.http import JsonResponse, HttpResponse
from .models import Task
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from .models import Task, CPAsList, CPA_Client, TaskType, Document
from .forms import TaskDetails
from django.contrib.auth.decorators import login_required
# Create your views here.
#login_required
def home(request):
context = {
'tasks': Task.objects.all()
}
return render(request, 'crm/home.html', context)
class TaskListView(ListView):
model = Task
template_name = 'crm/home.html'
context_object_name = 'tasks'
ordering = ['-Date_Added']
class TaskDetailView(DetailView):
model = Task
class TaskDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Task
success_url = '/'
def test_func(self):
task = self.get_object()
if self.request.user == task.Author:
return True
return False
class TaskCreateView(LoginRequiredMixin, CreateView):
model = Task
fields = '__all__'
success_url = '/'
def model_form_upload(self, form):
if request.method == 'POST':
form = TaskDetails(request.POST, request.FILES)
if form.is_valid():
form.instance.Author = self.request.user
return super().model_form_upload(form)
else:
form = TaskDetails()
return render(request, 'crm-home', {'form': form})
class TaskUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Task
fields = '__all__'
#success_url = '/'
def model_form_upload(self, form):
if request.method == 'POST':
form = TaskDetails(request.POST, request.FILES)
if form.is_valid():
form.Author = self.request.user
return super().model_form_upload(form)
else:
form = TaskDetails()
return render(request, 'crm-home', {'form': form})
def test_func(self):
task = self.get_object()
if self.request.user == task.Author:
return True
return False
def contact(request):
return render(request, 'crm/contact.html')
def update_counter(request):
if request.method == 'POST':
counterValue = request.POST['counter']
startTime = request.POST['timestamp']
print(counterValue)
print(startTime)
message = 'update successful'
return HttpResponse(message)
#AJAX
def load_cities(request):
country_id = request.GET.get('country_id')
cities = City.objects.filter(country_id=country_id).all()
return render(request, 'persons/city_dropdown_list_options.html', {'cities': cities})
# return JsonResponse(list(cities.values('id', 'name')), safe=False)
Your Task model has no name field. The Client_of_CPA field is a ForeignKey to the CPA_Client model:
class TaskDetails(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['Client_of_CPA'].queryset = CPA_Client.objects.none()
class Meta:
model = Task
fields = '__all__'
Your TaskCreateView and TaskUpdateView do not use your form however, you need to specify this with:
class TaskCreateView(LoginRequiredMixin, CreateView):
model = Task
form_class = TaskDetails
success_url = '/'
template_name = 'crm-home'
def form_valid(self, form):
form.instance.Author = self.request.user
return super().form_valid(form)
class TaskUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Task
form_class = TaskDetails
success_url = '/'
template_name = 'crm-home'
def form_valid(self, form):
form.instance.Author = self.request.user
return super().form_valid(form)
def test_func(self):
task = self.get_object()
return self.request.user == task.Author
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')