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
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 create a PostModel(just like instagram) and while the form is created to connect the user to the model with One-to-one/foreign key relationship, anyway I'm getting a problem while trying to upload an image and the db doesn't updates.
I've tried this solution
...
# models.py
from django.contrib.auth.models import User
from django.conf import settings
class Post(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
description = models.CharField(max_length=255, blank=True)
image = models.ImageField(upload_to='images')
uploaded_at = models.DateTimeField(auto_now_add=True)
...
# forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('description', 'image', )
def save(self, commit=True):
if commit:
Post.save()
return Post
...
# views.py
def account(request):
post = PostForm(request.POST, request.FILES)
if request.method == "POST":
if post.is_valid():
post.save(commit=False)
post.owner = request.user
post.save(commit=True)
messages.success(request, f"you had successfully updated your profile image")
return redirect("main:account")
else:
for msg in form.error_messages:
messages.error(request, f"{msg}: {form.error_messages[msg]}")
return render(request = request,
template_name = "main/account.html",
context={'PostForm':post})
post = PostForm()
return render(request = request,
template_name = "main/account.html",
context={'PostForm':post})
You should not override the def save() method, this is fine as it is now, so:
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('description', 'image', )
# no save
as for the view, you need to add the owner to the object, but here you are adding it to the form, and that thus has no effect (on the object):
from django.contrib.auth.decorators import login_required
#login_required
def account(request):
post = PostForm(request.POST, request.FILES)
if request.method == 'POST':
if post.is_valid():
post.instance.owner = request.user
post.save()
messages.success(request, f'you had successfully updated your profile image')
return redirect('main:account')
# …
I would also advise to rename post to post_form, since this is a form, not a post object.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
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?
Literaly like title say...check the picture. When i try to make new Post it says i made it but it wont show up on admin page nor in detail.html.
http://prntscr.com/n0pfrv
here is my code for post model
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(help_text="A short label, generally used in URLs.",default='', max_length=100)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
ordering = ['-date_posted']
def save(self):
slug = self.title
def get_absolute_url(self):
return reverse('detail', kwargs={'slug':self.slug})
def __str__(self):
return self.title
admin.py
from django.contrib import admin
from .models import Post
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'slug', 'date_posted', 'author']
list_filter = ['title', 'date_posted']
prepopulated_fields = { 'slug': ('title',)}
admin.site.register(Post, PostAdmin)
views.py in app called blog were i have model Post also
from django.contrib import messages
from . models import Post
from django.core.mail import send_mail
from django.views.generic import DeleteView, ListView
def index_view(request):
return render(request, 'blog/index_view.html')
def blog_view(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/blog_view.html', context)
class PostDetailView(DeleteView):
model = Post
template_name = 'blog/detail.html'
context_object_name = 'post'
If you need any other of my code im gonna post it
You don't actually save the data in your save(self) method:
def save(self):
slug = self.title
super(Post, self).save(*args, **kwargs)
You should call the real save method as mentioned in the docs:
Overriding predefined model methods
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')