I'm trying to update an item(book) present in the database, Even though I've added instance so that a new item is not created but instead the item is only updated, but unfortunately it's not working as it is supposed to, Instead of updating the item, a new item is being created, am I missing something in here?
models.py
class Book(models.Model):
book_name = models.CharField(max_length= 100)
author_name = models.CharField(max_length=100)
publisher = models.CharField(max_length=100)
published_on = models.DateTimeField(blank=True, null=True)
Language = models.CharField(max_length=100)
image = models.ImageField(blank = True, upload_to='images/')
created = models.DateTimeField(auto_now_add = True)
def __str__(self):
return self.book_name
#property
def imageURL(self):
try:
url = self.image.url
except:
url = " "
return url
views.py
def book_register(request):
if request.method == 'POST':
form = BookForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('/')
else :
return render(request, 'crud_operation/book_form.html', {'form': form})
else:
form = BookForm()
context = {'form':form}
return render(request,'crud_operation/book_form.html',context)
def book_update(request,pk):
book = Book.objects.get(id=pk)
form = BookForm(instance = book)
if request.method == 'POST':
form = BookForm(request.POST, request.FILES, instance=book)
if form.is_valid():
form.save()
return redirect('/')
context = {'form':form}
return render(request, 'crud_operation/book_form.html',context)
urls.py
urlpatterns = [
path('create-book/',views.book_register, name = 'books'),
path('update-book/<int:pk>/',views.book_update, name = 'book_update'),
]
forms.py
class BookForm(ModelForm):
class Meta:
model = Book
fields = '__all__'
widgets = {
'published_on': DateInput(attrs={'type': 'date'})
}
Related
I know that I can use #login_required but it is only used when we store user in User But in my case I stored model in form So it is not working for me. Also my created user is not getting authenticated when I use user.is_authenticated So I need custom login_required decorator which can be use to stop anyone from accessing direct url (confidential URl which are only accessed when you Login).
forms.py
class usrForm(forms.ModelForm):
password = forms.CharField(initial=123)
class Meta:
model = Person
fields = ('first_name','last_name','username','email','password','position')
def __init__(self, *args, **kwargs):
super(usrForm,self).__init__(*args,**kwargs)
self.fields['position'].empty_label = "Select"
class usrChange(forms.ModelForm):
class Meta:
model = Person
fields = ('username','password')
widgets= {
'password' : forms.PasswordInput(),
}
class loginForm(forms.ModelForm):
class Meta:
model = Person
fields = ('username','password')
widgets= {
'password' : forms.PasswordInput(),
}
models.py
class Position(models.Model):
title = models.CharField(max_length=50)
def __str__(self):
return self.title
class Person(models.Model):
first_name = models.CharField(max_length=50,default='')
last_name = models.CharField(max_length=50,default='')
username = models.CharField(max_length=50,default='')
password = models.CharField(max_length=50,default='')
email = models.EmailField(max_length=50)
position = models.ForeignKey(Position, on_delete=models.CASCADE)
def __str__(self):
return self.username
views.py
def user_list(request):
context = {'user_list' : Person.objects.all()}
return render(request, "usr_list.html", context)
def user_chnged_list(request):
form = usrForm(request.POST)
if form.is_valid():
form.save()
context = {'user_list' : Person.objects.all()}
return render(request, "usr_list.html", context)
def user_form(request, id=0):
if request.method == "GET":
if id ==0:
form = usrForm(initial={'password': 123}) # register
else:
auser = Person.objects.get(pk=id)
form = usrForm(instance=auser) #update
return render(request, "usr_form.html",{'form': form})
else:
if id == 0:
form = usrForm(request.POST , initial={'password': 123}) # register
else:
auser = Person.objects.get(pk=id) #update
form = usrForm(request.POST,instance=auser)
if form.is_valid():
form.save()
return redirect('login')
def user_delete(request,id):
auser = Person.objects.get(pk=id)
auser.delete()
return redirect('list')
def user_login(request):
form = loginForm()
if request.method == 'POST':
form = loginForm(data=request.POST)
if form.is_valid():
username=form.cleaned_data.get('username')
password=form.cleaned_data.get('password')
i = Person.objects.filter(username=username,password=password).exists()
user = {'user_list' : Person.objects.filter(username=username,password=password)}
if i == True:
j = Person.objects.filter(username=username, position_id = 1).exists()
if j == True:
return redirect('list')
return render(request,"usr_wlc.html", user )
else:
messages.error(request, 'Invalid username or password!')
context = {'form':form}
return render(request,'usr_login.html',context)
def user_detail(request,id):
auser = Person.objects.get(pk=id)
form = usrChange(request.POST,instance=auser)
if form.is_valid():
form.save()
return redirect('login')
def user_logout(request):
return redirect('/')
def user_change(request,id):
auser = Person.objects.get(pk=id) #update
form = usrChange(request.POST,instance=auser)
return render(request, "usr_chnge.html",{'form': form})
I am trying to add created by whoever is logged in user but not getting that saved even though I am logged in. form.created_by = request.user is not adding logged in user.
def create_table_allotment(request):
form = TableAllotmentForm(request.POST or None)
context = {'form': form}
if request.method == 'POST':
if form.is_valid():
try:
form.save(commit=False)
form.created_by = request.user
form.save()
return redirect('order_management:table_allotment_home')
except IntegrityError as err:
print('err => ', err)
context['unique_error'] = 'User has already assigned table for today'
return render(request, 'orders/table_allotment/create.html', context)
Here are my models
class QOTs(models.Model):
name = models.CharField(max_length=50)
alias = models.CharField(max_length=10)
def __str__(self):
return str(self.name)
class Meta:
verbose_name_plural = "QOTs"
class TableAllotment(models.Model):
employee = models.ForeignKey(User, on_delete=models.PROTECT)
qot = models.ForeignKey(QOTs, on_delete=models.PROTECT)
club = models.CharField(max_length=20, default='POS-0001')
from_table = models.IntegerField()
to_table = models.IntegerField()
working_date = models.DateField(default=timezone.now)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='qot_creator')
created_at = models.DateTimeField(_("Created at"), auto_now_add=True, editable=False)
updated_at = models.DateTimeField(_("Updated at"), auto_now=True)
class Meta:
ordering = ('-id',)
unique_together = ('employee', 'working_date',)
Here is my form
class TableAllotmentForm(forms.ModelForm):
class Meta:
model = models.TableAllotment
fields = ["employee", "qot", "from_table", "to_table"]
Please help
form.save(commit=False) will return the instance wrapped by the form which you can then modify and call save on. Instead you are just calling save on the form again and also you are setting form.created_by = request.user i.e. you are setting an attribute on the form.
Instead you should directly modify the instance wrapped by the form:
def create_table_allotment(request):
form = TableAllotmentForm(request.POST or None)
context = {'form': form}
if request.method == 'POST':
if form.is_valid():
try:
form.instance.created_by = request.user
form.save()
return redirect('order_management:table_allotment_home')
except IntegrityError as err:
print('err => ', err)
context['unique_error'] = 'User has already assigned table for today'
return render(request, 'orders/table_allotment/create.html', context)
Note: TableAllotmentForm(request.POST or None) is an anti-pattern (It is possible for an empty form to be valid in certain conditions) and you should simply pass request.POST only if
request.method == "POST" else you should simply write
TableAllotmentForm().
An alternative approach to what Abdul Aziz Barkat has suggested would be to assign returned object of save()(Django-Docs) method like so obj = form.save(commit=False).
I would also add #login_required to the view
from django.contrib.auth.decorators import login_required
#login_required
def create_table_allotment(request):
if request.method == 'POST':
form = TableAllotmentForm(request.POST)
if form.is_valid():
try:
obj = form.save(commit=False)
obj.created_by = request.user
obj.save()
return redirect('order_management:table_allotment_home')
except IntegrityError as err:
print('err => ', err)
context['unique_error'] = 'User has already assigned table for today'
else:
form = TableAllotmentForm()
context = {'form': form}
return render(request, 'orders/table_allotment/create.html', context)
My English is not good.. Hope you understand that..
I(beginner) use django and python, and I try to upload multiple files.
finally i find working code but It is difficult to apply to the original code
What am I doing wrong?
(form.py, model.py is same each other)
working ex code(views.py)
def a(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
files = request.FILES.getlist("files")
if form.is_valid():
for f in files:
file_instance = Upload(file_upload=f)
file_instance.save()
return render(request, 'single_pages/about_me.html', {'form':form,})
# return HttpResponse(" File uploaded! ")
else:
form = UploadFileForm()
return render(request, 'single_pages/about_me.html', {'form': form})
my Spaghetti code(views.py)
def a(request, pk):
if request.method == 'POST':
comment_form = CommentForm(request.POST, request.FILES)
files = request.FILES.getlist('files')
if comment_form.is_valid():
comment = comment_form.save(commit=False)
comment.post = post
comment.author = request.user
comment.save()
for f in files:
file_instance = Comment(file_upload=f)
file_instance.save()
return redirect(comment.get_absolute_url())
else:
return redirect(post.get_absolute_url())
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = {'content', 'file_upload', 'head_image'}
files = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
head_image = models.ImageField(upload_to='blog/images/%Y/%m/%d/', blank=True)
file_upload = models.FileField(upload_to='blog/files/%Y/%m/%d/', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.author}::{self.content}'
def get_absolute_url(self):
return f'{self.post.get_absolute_url()}#comment-{self.pk}'
def get_file_name(self):
return os.path.basename(self.file_upload.name)
def get_file_ext(self):
return self.get_file_name().split('.')[-1]
What should I do..
thank you very much
My django project has multiple functions, one of them lets the user update its profile(User model"first_name, username and email" Profile model" bio and profile picture") this used to perfectly work until I added a follow sistem, it is like the whole Profile and User model doesnt exist anymore so when trying to edit those fields, the code returns a AttributeError: 'User' object has no attribute 'profile' error, saying this line of code on the views.py file is wrong form1 = UpdateProfileForm(request.POST or None, request.FILES, instance=request.user.profile), I think I am missing something on there or there is probably there is something wrong.
views.py
def profile(request, username=None):
profile, created = Profile.objects.get_or_create(user=request.user)
user = User.objects.get(username=username)
if username:
post_owner = get_object_or_404(User, username=username)
user_posts = Profile.objects.filter(user_id=post_owner)
is_following = Following.objects.filter(user=request.user, followed=user)
following_obj = Following.objects.get(user=user)
follower = following_obj.follower.count()
following = following_obj.followed.count()
else:
post_owner = request.user
user_posts = Profile.objects.filter(user=request.user)
args1 = {
'post_owner': post_owner,
'user_posts': user_posts,
'follower': follower,
'following': following,
'connection': is_following,
}
return render(request, 'profile.html', args1)
def edit_profile(request):
profile, created = Profile.objects.get_or_create(user=request.user)
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
form1 = UpdateProfileForm(request.POST or None, request.FILES, instance=request.user.profile)
if form.is_valid and form1.is_valid:
form.save()
form1.save()
return redirect('profile')
else:
form = EditProfileForm(instance=request.user)
form1 = UpdateProfileForm(instance=request.user)
args = {
'form': form,
'form1': form1,
}
return render(request, 'profile-edit.html', args)
models.py
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile_pic = models.ImageField(upload_to='profile_pics', null=True, blank=True, default='default.png')
bio = models.CharField(max_length=400, default=1, null=True)
connection = models.CharField(max_length = 100, blank=True)
follower = models.IntegerField(default=0)
following = models.IntegerField(default=0)
def __str__(self):
return f'{self.user.username} Profile'
class Following(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
followed = models.ManyToManyField(User, related_name="followed")
follower = models.ManyToManyField(User, related_name="follower")
#classmethod
def follow(cls, user, another_account):
obj, create = cls.objects.get_or_create(user = user)
obj.followed.add(another_account)
print("followed")
#classmethod
def unfollow(cls, user, another_account):
obj, create = cls.objects.get_or_create(user = user)
obj.followed.remove(another_account)
print("unfollowed")
def __str__(self):
return f'{self.user.username} Profile'
forms.py
class EditProfileForm(UserChangeForm):
class Meta:
model = User
fields = (
'first_name',
'username',
'email',
)
exclude = ('password',)
class UpdateProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = (
'bio',
'profile_pic',
)
If you need to see more code please let me know;)
Try this:
def edit_profile(request):
profile, created = Profile.objects.get_or_create(user=request.user)
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
form1 = UpdateProfileForm(request.POST or None, request.FILES, instance=request.user.profile)
if form.is_valid() and form1.is_valid():
form.save()
form1.save()
return redirect('profile')
else:
form = EditProfileForm(instance=request.user)
form1 = UpdateProfileForm(instance=profile)
args = {
'form': form,
'form1': form1,
}
return render(request, 'profile-edit.html', args)
The solution I found temporarily to solve this problem is to just changed Profile's user object to OneToOneField and Following's user model to ForeignKey.
views.py
form = StudentTaskForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.instance.user = User.objects.get(id=request.user.id)
obj = form.save(commit=False)
obj.student = request.user
obj.todo = qs
obj.level = instance
obj.save()
ImageFormSet = modelformset_factory(Images,
form=ImageForm,min_num=0,
max_num=3, validate_min=True,extra=3)
if request.method == 'POST':
formset = ImageFormSet(request.POST, request.FILES,
queryset=Images.objects.none())
if formset.is_valid():
for form in formset.cleaned_data:
try:
image = form['image']
Images.objects.create(post=todo[0],image=image)
except KeyError:
pass
return redirect('student:dashboard')
else:
formset = ImageFormSet(queryset=Images.objects.none())
forms.py:
class StudentTaskForm(forms.ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-
control',' type': "text",'placeholder':'Enter Title'}))
content = forms.CharField(widget=SummernoteWidget())
class Meta:
model = Task
fields = [
'title',
'content',
]
widgets = {
'content': SummernoteWidget(),
}
def clean_object(self):
instance = self.instance
class ImageForm(forms.ModelForm):
image = forms.ImageField(label='Image')
class Meta:
model = Images
fields = ('image', )
Im using formsets for saving images.A task may contain a maximum of three images.
In models.py i have :
class Task(models.Model):
level = models.ForeignKey(Level, on_delete=models.CASCADE)
todo = models.ForeignKey(ToDo,
on_delete=models.CASCADE,related_name='todo')
student = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=150)
content = models.TextField()
timestamp = models.TimeField(auto_now=True)
datestamp = models.DateField( auto_now=True)
like =
models.ManyToManyField(User,related_name='user_likes',blank=True)
is_verified=models.BooleanField(default=False,blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('student:dashboard')
objects = PostManager()
#property
def comments(self):
instance = self
qs = Comment.objects.filter_by_instance(instance)
return qs
#property
def get_content_type(self):
instance = self
content_type =
ContentType.objects.get_for_model(instance.__class__)
return content_type
class Images(models.Model):
post = models.ForeignKey(Task,
default=None,on_delete=models.CASCADE)
image = models.ImageField(verbose_name='Image',blank=True)
def __str__(self):
return self.post.title
Im creating another model to save the images that belong to a particular task
How do i target the post when submitting the form.?
Images.objects.create(post=todo[0],image=image)
Im confused what to put in post=? .By the definition of the model the post is a foreign key to a task object .i want this task object to be the model for currently submitting form model from the StudentTaskForm
You should be using an inline formset, which will handle this for you.
ImageFormSet = inlineformset_factory(Task, Images,
form=ImageForm, min_num=0,
max_num=3, validate_min=True, extra=3)
formset = ImageFormSet(request.POST, request.FILES, instance=obj)
if formset.is_valid():
formset.save()
Here there's no need to iterate at all.