I have a image field
avatar = models.ImageField(upload_to="avatar", null=True, blank=True)
and using view
class EditView(SuccessMessageMixin, UpdateView):
model = MysiteUser
form_class = MysiteUserForm
pk_url_kwarg = 'pk'
template_name = 'update_form.html'
success_url = '/myprofile/'
success_message = "Zmiany zostaĆy wprowadzone."
def form_valid(self, form):
image_to_del = MysiteUser.objects.get(username=form.instance)
print("Na dysku plik", image_to_del.avatar)
print("Formularz i pole 'avatar'", form.instance.avatar)
if form.instance.avatar != self.request.user.avatar:
self.request.user.avatar.delete()
return super().form_valid(form)
in template form
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="save" />
</form>
I want change link like below
<p><label for="id_avatar">Zdjecie:</label> Now: avatar/n.jpg
on image, how can I do this?
Related
views.py
class PostCreatView(LoginRequiredMixin, CreateView):
model = Posts
fields = ['image', 'caption']
template_name = 'home/creat-post.html'
success_url = '/home/'
def form_valid(self,form):
form.instance.user = self.request.user
return super().form_valid(form)
models.py
class Posts(models.Model):
caption = models.CharField(max_length=2200)
date_posted = models.DateTimeField(default=timezone.now())
image = models.ImageField( upload_to='PostsImages')
user = ForeignKey(User, on_delete=models.CASCADE ,related_name='UserPosts')
def __str__(self):
return f"Post {self.id} ({self.user.username})'s"
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
#img = make_square(img, 1080, 1080)
img.save(self.image.path)
class Meta:
ordering = ['-date_posted']
creat-post.html
{% extends "home/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div>
<form method="POST">
<fieldset>
<legend >Creat Post</legend>
{% csrf_token %}
{{ form|crispy }}
</fieldset>
<button class="btn btn-primary" type="submit">Post</button>
</form>
</div>
{% endblock %}
So I created a creatview to add create new post. However when I go to the link and add photo then hit submit, it gives me as I haven't uploaded an image.
However, I am able to add images to a new Post from the admin normally.
Try to add enctype in your template:
<form method="post" enctype="multipart/form-data">
I'm creating 2 forms on one template in cookiecutter-django. I have both forms working on a normal django project but when I migrated them to cookiecutter-django, the forms did not work on the user_detail template.
This is the forms.py
class NarrateForm(ModelForm):
class Meta:
model = Narrate
fields = [
'title',
'body',
]
exclude = ('status',)
class TranslateForm(ModelForm):
class Meta:
model = Translate
fields = [
'title',
'body',
]
exclude = ('status',)
These are the views.py of forms that I have:
class TranslateFormView(FormView):
form_class = TranslateForm
template_name = 'user_detail.html'
def post(self, request, *args, **kwargs):
add_translation = self.form_class(request.POST)
add_narration = NarrateForm()
if add_translation.is_valid():
add_translation.save()
return self.render_to_response(
self.get_context_data(
success=True
)
)
else:
return self.render_to_response(
self.get_context_data(
add_translation=add_translation,
)
)
class NarrateFormView(FormView):
form_class = NarrateForm
template_name = 'users/user_detail.html'
def post(self, request, *args, **kwargs):
add_narration = self.form_class(request.POST)
add_translation = TranslateForm()
if add_narration.is_valid():
add_narration.save()
return self.render_to_response(
self.get_context_data(
success=True
)
)
else:
return self.render_to_response(
self.get_context_data(
add_narration=add_narration,
)
)
Now this is the view of the user_details from cookiecutter-django
class UserDetailView(LoginRequiredMixin, DetailView):
model = User
slug_field = "username"
slug_url_kwarg = "username"
user_detail_view = UserDetailView.as_view()
This is the code on the template which works on the old django project
<form method="POST" action="#">
{% csrf_token %}
{{ add_narration }}
<button type="submit" name="submit" value="Send Narration">Submit Narration</button>
</form>
<form method="POST" action="#">
{% csrf_token %}
{{ add_translation }}
<button type="submit" name="submit" value="Send Narration">Submit Narration</button>
</form>
I've been trying to make this work for more than 2 hours already and had no luck.
A possible solution could be creating a basic form (extend django.forms.Form) in the forms.py file, manually creating the fields and the modela later on in the views.py file.
give the submit inputs different names as shown here
<form method="POST" action="#">
{% csrf_token %}
{{ add_narration }}
<button type="submit" name="narrationsubmit" value="Send Narration">Submit Narration</button>
</form>
<form method="POST" action="#">
{% csrf_token %}
{{ add_translation }}
<button type="submit" name="transaltionsubmit" value="Send Narration">Submit Narration</button>
</form>
Then handle them as below in your view.
def handleforms(request):
if request.method =="POST" and "narrationsubmit" in request.post:
//process
elif request.method =="POST" and "transaltionsubmit" in request.post:
//process
NB: this is for a function based view. format it for a CBV
I am trying to use custom HTML to render form field elements. However, now the data is not saving. The data is saving if I use the default form.as_p method.
Related template:
<!--DOES NOT SAVE DATA-->
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.description }}
<input type="submit" value="Update"/>
</form>
<!--SAVES DATA-->
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update"/>
</form>
Related UpdateView:
class ProfileEditView(UserPassesTestMixin, UpdateView):
model = Profile
form_class = ProfileCreateForm
template_name = 'update_profile_backup.html'
def get_success_url(self):
return reverse('profile', kwargs={'pk': self.object.pk})
def test_func(self):
obj = self.get_object()
print(obj.user == self.request.user)
return obj.user == self.request.user
Related ModelForm:
class ProfileCreateForm(forms.ModelForm):
class Meta:
model = Profile
fields = 'platform', 'content_niche', 'youtube_channel_id', 'description','profile_img', 'v_id_0', 'v_id_0_title', 'v_id_0_desc', \
'v_id_1', 'v_id_1_title', 'v_id_1_desc', 'v_id_2', 'v_id_2_title', 'v_id_2_desc'
Is it because the custom render method is not validating the form data? If so, how would I do that with an updateview?
I have created a Child Model connected to the Parent Model via ForeignKey. When i tried to create a Child instance it returns nothing. I am not sure in my views child.Parent is working properly or not. I would appreciate helping me solve this.
Here's my code:
models.py:
Parent(models.Model):
Parent = models.CharField(max_length=30)
def __str__(self):
return self.id
def get_absolute_url(self):
return reverse("parents:detail", kwargs={"id": self.id})
Child(models.Model):
Parent = models.ForeignKey(Parent, related_name='children')
Child = models.CharField(max_length=30)
def __str__(self):
return self.id
forms.py:
ChildForm(models.ModelForm):
Parent = forms.CharField(widget=forms.HiddenInput)
class Meta:
model = Child
fields = ["Parent", "Child",
]
views.py:
def child_create(request, id):
parent_instance = get_object_or_404(Parent, id=id)
form = ChildForm(request.POST or None)
if form.is_valid():
child = form.save(commit=False)
child.Parent = form.cleaned_data.get('parent_id')
child.save()
return HttpResponseRedirect(parent_instance.get_absolute_url())
context = { 'form':form, 'parent_instance':parent_instance,}
return render(request, "child_create.html", context)
templates/child_create.html:
{{if parent_instance.id}}
<form class="nomargin" method='POST' action='' enctype='multipart/form-data'>{% csrf_token %}
{{ form|crispy }}
<input type='hidden' name='parent_id' value='{{ parent_instance.id }}' />
<input type='submit' value='Add a Child' class='btn btn-default' />
</form>
{% endif %}
Use ModelChoiceField instead of CharField
forms.py:
ChildForm(models.ModelForm):
Parent = forms.ModelChoiceField(queryset=Parent.objects.all(),
widget=forms.HiddenInput())
class Meta:
model = Child
fields = ["Parent", "Child",]
views.py:
def child_create(request, id):
parent_instance = get_object_or_404(Parent, id=id)
form = ChildForm(request.POST or None)
if form.is_valid():
child = form.save(commit=False)
child.save()
return HttpResponseRedirect(parent_instance.get_absolute_url())
context = { 'form':form, 'parent_instance':parent_instance,}
return render(request, "child_create.html", context)
templates/child_create.html:
{{if parent_instance.id}}
<form class="nomargin" method='POST' action='' enctype='multipart/form-data'>
{% csrf_token %}
{{ form|crispy }}
<input type='hidden' name='Parent' value='{{ parent_instance.pk }}' />
<input type='submit' value='Add a Child' class='btn btn-default' />
</form>
{% endif %}
A user will have photos which will be related with their specific album.
So this was the model for that:
class Album(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=200)
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
update = models.DateTimeField(auto_now_add=False, auto_now=True)
class Photo(models.Model):
photo_privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
user = models.ForeignKey(User)
caption = models.TextField()
image = models.ImageField(upload_to=get_upload_file_name)
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
Views.py:
def create_album(request, user_name):
user = User.objects.get(username=unquote(user_name))
if request.method=='POST':
pform = AlbumPhotoForm(request.POST, request.FILES)
aform = AlbumForm(request.POST)
p_valid = pform.is_valid()
a_valid = aform.is_valid()
if p_valid and a_valid:
photo = pform.save(commit=False)
album = aform.save(commit=False)
photo.user = user
album.user = user
album.save()
photo.album = album
photo.save()
return HttpResponseRedirect('/'+user.username+'/photos')
else:
return render(request, 'create_album.html',{
'pform':pform,
'aform':aform
})
else:
pform = AlbumPhotoForm()
aform = AlbumForm()
return render(request, 'create_album.html', {
'pform':pform,
'aform':aform
})
And the form:
<form action="/{{ user.username }}/create_album/" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ aform.as_p }}
{{ pform.as_p }}
<input type="submit" value="Create and Upload Album"/>
</form>
This works fine if I only have to upload one file (photo) with that form.
Update:
However what I want to do is, show minimum of three input for uploading photos to the new album:
<form action="/{{ user.username }}/create_album/" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ aform.as_p }}
{{ pform.as_p }}
{{ pform.as_p }}
{{ pform.as_p }}
<input type="submit" value="Create and Upload Album"/>
</form>
When doing so, only the last pform is gets saved. And the other two pform's are ignored. How do I get to save all the three forms of photo (pform) accordingly?
Or is there any other way around? Your help will be much appreciated! Thank you.
Use formsets. They do exactly what you want:
from django.forms.models import formset_factory
PhotoFormSet = formset_factory(AlbumPhotoForm, can_delete=False,
min_num=1, validate_min=True,
max_num=3, validate_max=True,
extra=3)
def create_album(request, user_name):
user = User.objects.get(username=unquote(user_name))
if request.method=='POST':
form = AlbumForm(request.POST)
formset = PhotoFormSet(request.POST, request.FILES)
if all([form.is_valid(), formset.is_valid()]):
album = form.save(commit=False)
album.user = user
album.save()
for photo_form in formset:
if photo_form.cleaned_data:
photo = photo_form.save(commit=False)
photo.album = album
photo.user = user
photo.save()
return redirect('/%s/photos' % user.username )
else:
form = AlbumForm()
formset = PhotoFormSet()
return render(request, 'create_album.html',
{'form': form, 'formset': formset})
And template may look like this:
<form action="." method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<table>
{{ formset }}
</table>
<input type="submit" value="Create and Upload Album"/>
</form>