django issue,form is not display.? - django

I have issue in Django,I am trying to make form which is working for admin side but I want to saw same form in front end this think done some mistake so its not display.
model.py class
class Product(models.Model):
title = models.CharField(max_length=120)
description = models.TextField(null=True, blank=True)
category = models.ManyToManyField(Category, null=True, blank=True)
price = models.DecimalField(decimal_places=2, max_digits=100, default=29.99)
sale_price = models.DecimalField(decimal_places=2, max_digits=100,\
null=True, blank=True)
slug = models.SlugField(unique=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
active = models.BooleanField(default=True)
update_defaults = models.BooleanField(default=False)
def __unicode__(self):
return self.title
class Meta:
unique_together = ('title', 'slug')
def get_price(self):
return self.price
def get_absolute_url(self):
return reverse("single_product", kwargs={"slug": self.slug})
my admin.py
from .models import Product, ProductImage, Variation, Category
admin.site.register(ProductImage)
admin.site.register(Variation)
admin.site.register(Category)
from products.models import Product
admin.site.register(Product)
html file
{% extends 'base.html' %}
{% load staticfiles %}
{% block head_title %}
Products ||
{% endblock %}
{% block styles %}
.jumbotron {
/*color: red;*/
}
{% endblock %}
{# Comments here #}
{% block content %}
<div class='col-sm-6 col-sm-offset-3' style='margin-top: 50px;'>
<h1>{{ form_title }}</h1>
<form method="post" enctype="multipart/form-data">
<div style="background-color:#f2f2f2" ><br />
<div style="width:25%; margin:0px auto;">
{% csrf_token %}
{{ form.as_table}}
<input type='submit' value='{% if submit_btn %}{{ submit_btn }}{% else %}Submit{% endif %}' class='btn btn-default' />
</div>
</div>
</form>
</div>
{% endblock %}
view.py
from django.shortcuts import render, Http404
from marketing.forms import EmailForm
from marketing.models import MarketingMessage, Slider
from .models import Product, ProductImage
def search(request):
try:
q = request.GET.get('q')
except:
q = None
if q:
products = Product.objects.filter(title__icontains=q)
context = {'query': q, 'products': products}
template = 'products/results.html'
else:
template = 'products/home.html'
context = {}
return render(request, template, context)
def home(request):
sliders = Slider.objects.all_featured()
products = Product.objects.all()
template = 'products/home.html'
context = {
"products": products,
"sliders": sliders,
}
return render(request, template, context)
def all(request):
products = Product.objects.all()
context = {'products': products}
template = 'products/all.html'
return render(request, template, context)
def deals(request):
products = Product.objects.all()
template = 'deals.html'
context = {
"products": products,
}
return render(request, template, context)
def single(request, slug):
try:
product = Product.objects.get(slug=slug)
#images = product.productimage_set.all()
images = ProductImage.objects.filter(product=product)
context = {'product': product, "images": images}
template = 'products/single.html'
return render(request, template, context)
except:
raise Http404

You should do like this:
def my_view(request):
form = my_form()
if request.method == "POST":
form = my_form(request.POST, request.FILES)
if form.is_valid():
#do something with cleaned_data
form.save()
else:
return render_to_response("your_template.html", {'form':form}, context_instance=RequestContext(request))
else:
form = my_form()
return render_to_response("your_template.html", {'form':form}, context_instance=RequestContext(request))
and in your template use like:
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
</form>

Related

When trying to update an instance of related models I get the Ids on the template instead of the names, using {{form}}

URLS.py
urlpatterns = [
path('stock/update/<int:pk>/', views.StockUpdateView, name='stock-update'),
VIEWS.py
def StockUpdateView(request, pk):
stock = Stock.objects.get(id=pk)
form = StockForm(instance=stock)
if request.method == 'POST':
form = StockForm(request.POST, instance=stock)
if form.is_valid():
form.save()
return redirect('/inventory/stock')
context = {"form": form}
return render(request, 'inventory/update-stock.html', context)
TEMPLATE.html
<form action="" method="POST" class="row g-3">
<div class="col-auto">
<h6>Stock update form:</h6>
{% csrf_token %}
{% for field in form %}
<div class="form-control">
{{field}}
</div>
{% endfor %}
MODEL.py
class Stock(models.Model):
class Meta:
verbose_name_plural = "Stocks"
name = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
product_id = models.ForeignKey('products.Product', on_delete=models.CASCADE)
quantity = models.IntegerField(default=0)
product_price = models.DecimalField(max_digits=19, decimal_places=2, default=0 ,validators=[MinValueValidator(0)])
def get_absolute_url(self):
return reverse("stock-update", args=[self.pk])
def __str__(self):
return f"{self.product_id} {self.quantity} {self.product_price}"
I have changed from using the {{ form }} tag to looping over the fields trying to get the name of the related table instead of the IDs.

Django how to add a form to a DetailView with FormMixin

I am attempting to add a form for comments to a DetailView. The DetailView displays notes for specific projects. So the comments have a foreign key that is the specific note and the note has a foreign key for the specific project.
I am attempting to use FormMixin with DetailView. So far I have not bee successful. Currently I can get the form to display but it does not save and in the terminal I see the following error Method Not Allowed (POST): /projects/project/1/note/1/
I can get these to work separately but not with the form in the DetailView.
Here are my models:
class ProjectNotes(models.Model):
title = models.CharField(max_length=200)
body = tinymce_models.HTMLField()
date = models.DateField(auto_now_add=True)
project = models.ForeignKey(Project, default=0, blank=True, on_delete=models.CASCADE, related_name='notes')
def __str__(self):
return self.title
class ProjectNoteComments(models.Model):
body = tinymce_models.HTMLField()
date = models.DateField(auto_now_add=True)
projectnote = models.ForeignKey(ProjectNotes, default=0, blank=True, on_delete=models.CASCADE, related_name='comments')
The View:
class ProjectNotesDetailView(DetailView, FormMixin):
model = ProjectNotes
id = ProjectNotes.objects.only('id')
template_name = 'company_accounts/project_note_detail.html'
comments = ProjectNotes.comments
form_class = NoteCommentForm
def form_valid(self, form):
projectnote = get_object_or_404(ProjectNotes, id=self.kwargs.get('pk'))
comment = form.save(commit=False)
comment.projectnote = projectnote
comment.save()
return super().form_valid(form)
def get_success_url(self):
return reverse('project_detail', args=[self.kwargs.get('pk')])
The form:
class NoteCommentForm(forms.ModelForm):
class Meta:
model = ProjectNoteComments
fields =['body',]
widgets = {
'body': forms.TextInput(attrs={'class': 'form-control'})
}
The template:
% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="section-container container">
<div class="project-entry">
<h2>{{ projectnotes.title }}</h2>
<p>{{ projectnotes.body | safe }}</p>
</div>
<div><b>Comments on {{projectnotes.title}}</b></div>
{% if projectnotes.comments.all %}
{% for comment in projectnotes.comments.all %}
<div class="notecomments" style="padding: 10px;">
{{ comment.body | safe }}
</div>
{% endfor %}
{% else %}
<p>No comments have been have been added yet.</p>
{% endif %}
<h2>add note</h2>
<h1>Add Comment</h1>
<form action="" method="post">
{% csrf_token %}
{{ form.media }}
{{ form|crispy }}
<input type="submit" value="save">
</form>
{% endblock content %}
Try to change the order between DetailView and FormMixin in ProjectNotesDetailView then implement the post method (enabled by the `FormMixin):
class ProjectNotesDetailView(FormMixin, DetailView):
model = ProjectNotes
id = ProjectNotes.objects.only('id')
template_name = 'company_accounts/project_note_detail.html'
comments = ProjectNotes.comments
form_class = NoteCommentForm
def form_valid(self, form):
projectnote = get_object_or_404(ProjectNotes, id=self.kwargs.get('pk'))
comment = form.save(commit=False)
comment.projectnote = projectnote
comment.save()
return super().form_valid(form)
def get_success_url(self):
return reverse('project_detail', args=[self.kwargs.get('pk')])
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
Check how to use formmixin with detailview (documentation).

Jinja for loop is not working after adding qs to iterator. Django

In my project I am using django-filter and when I am adding .qs to {% for product in products %} {% for product in products.qs %}. In the template result filters are displaying, but products are not. Here are my files.
html
<form method="get">
{{ filterA.form.as_p }}
{{ filterB.form.as_p }}
<input type="submit" value="Press" class="filter-go">
</form>
{% for product in products.qs %}
<div class="product" onclick="location.href='{% url 'items' product.id %}'">
<img src="{{product.image.url}}" alt="Img is not found (">
<p class="product-title">{{ product.title }}</p>
<b><p class="product-price">{{ product.price }} ₽</p></b>
</div>
{% endfor %}
views.py
def index(request):
con = {
'services': Service.objects.all(),
'products': Product.objects.all(),
'galery': GaleryImage.objects.all(),
'product_types': Category.objects.all(),
'filterA': FilterA(request.GET, queryset=Product.objects.all()),
'filterB': FilterB(request.GET, queryset=Product.objects.all()),
}
return render(request, 'index.html', con)
def product(request, pk=None):
try:
a = Product.objects.get(id=pk)
except:
return render(request, 'error404.html')
context = {
'id': pk,
'product': a,
}
return render(request, 'product.html', context)
filters.py
class FilterA(django_filters.FilterSet):
class Meta:
model = Product
fields = ['category']
class FilterB(django_filters.FilterSet):
CHOICES = (
('ascending', 'По дате (А-Я)'),
('descending', 'По дате (Я-А)'),
)
CHOICES2 = (
('price_low', 'По цене по возрастанию'),
('price_high', 'По цене по убыванию'),
)
orderDate = django_filters.ChoiceFilter(choices=CHOICES, method='filter_by_date', label='')
orderPrice = django_filters.ChoiceFilter(choices=CHOICES2, method='filter_by_price', label='')
class Meta:
model = Product
fields = {
'price': ['lt', 'gt'],
}
def filter_by_date(self, queryset, name, value):
expr = 'date' if value == 'ascending' else '-date'
return queryset.order_by(expr)
def filter_by_price(self, queryset, name, value):
expr = 'price' if value == 'price_low' else '-price'
return queryset.order_by(expr)
models.py
class Product(models.Model):
category = models.ForeignKey(Category, verbose_name='Կատեգորիա', on_delete=models.CASCADE)
title = models.CharField(max_length=225, verbose_name='Ապրանքի վեռնագիրը')
description = models.TextField(verbose_name='Նկարագրություն', null=True)
image = models.ImageField(upload_to='product_img', verbose_name='Նկարը')
price = models.DecimalField(max_digits=9, decimal_places=2, verbose_name='Գին')
date = models.DateField(verbose_name='Ամսաթիվը որի ժամանակ ստեղծվել է')
def __str__(self):
return self.title
I suspect the problem is that you're expecting products.qs to do some filtering as per some logic from django-filter. However, your template's context variable for "products" is a simple queryset. You likely need to use {% for product in filterA.qs %} or {% for product in filterB.qs %} depending on which filtering you'd like to use.

Image not being replaced when updating Django ImageField

I am working on a blog in Django and i am trying to update the image of my model BlogPost using a ModelForm.
Initialy , when creating the post, the image is being uploaded with no problems in media/posts. However , nothing happens when trying to update the existing image with another one ( or to add an image to a post already created without one).
I have found a solution online for this issue and that was to override the save() method for the model. I did that but still nothing seems to happen. Clearly, I am doing something wrong.
My code below:
views.py:
def blog_post_update_view(request,slug):
obj = get_object_or_404(BlogPost.objects.filter(user=request.user), slug=slug)
form = BlogPostModelForm(request.POST or None, instance=obj)
if form.is_valid():
form.save()
print(obj.image)
return redirect(obj.get_absolute_url()+"/detail/")
template_name = 'blog/form.html'
context = {"title": f"Update {obj.title}", "form": form}
return render(request, template_name, context)
models.py:
class BlogPost (models.Model):
# id = models.IntegerField() # pk
user= models.ForeignKey(User, default=1, null=True, on_delete=models.SET_NULL)
image=models.ImageField( upload_to='posts/',blank=True,null=True)
title=models.CharField(max_length=120)
slug= models.SlugField() # hello world -> hello-world
content=models.TextField(null=True,blank=True)
publish_date=models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True)
timestamp=models.DateTimeField(auto_now_add=True)
updated=models.DateTimeField(auto_now=True)
objects = BlogPostManager()
class Meta:
ordering = ['-publish_date', '-updated', '-timestamp']
def get_content_length(self):
return len(self.content)
def get_absolute_url(self):
return f"/blog/{self.slug}"
def get_edit_url(self):
return f"{self.get_absolute_url()}/edit"
def get_delete_url(self):
return f"{self.get_absolute_url()}/delete"
def save(self, *args, **kwargs):
try:
this = BlogPost.objects.get(id=self.id)
if this.image!= self.image:
this.image.delete()
except: pass
super(BlogPost, self).save(*args, **kwargs)
def __str__(self):
return self.title
forms.py:
class BlogPostModelForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title','image', 'slug', 'content', 'publish_date']
def clean_title(self, *args, **kwargs):
instance = self.instance
print('instance is: ',instance)
title = self.cleaned_data.get('title')
qs = BlogPost.objects.filter(title__iexact=title)
if instance is not None:
qs = qs.exclude(pk=instance.pk) # id=instance.id
if qs.exists():
raise forms.ValidationError("This title has already been used. Please try again.")
return title
blog/templates/form.html:
<!doctype html>
{% extends "blog/base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block head_title %}
{{title}}
{% endblock %}
{% block content %}
{% if title %}
<h1>{{ title }}</h1>
{% endif %}
<form method='POST' enctype="multipart/form-data" action='.'> {% csrf_token %}
{{ form|crispy}}
<button type='submit'>Send</button>
</form>
{% endblock %}
your view should be like:
def blog_post_update_view(request,slug):
obj = get_object_or_404(BlogPost.objects.filter(user=request.user), slug=slug)
if request.method == "POST":
form = BlogPostModelForm(request.POST, request.FILES, instance=obj)
if form.is_valid():
form.save()
return redirect(obj.get_absolute_url()+"/detail/")
form = BlogPostModelForm(instance=obj)
template_name = 'blog/form.html'
context = {"title": f"Update {obj.title}", "form": form}
return render(request, template_name, context)

Django - Modelform not rendering

I created a form to update a User's profile, however when I run it, there are no errors, but when I try to open up the page, the header appears but the UpdateBioForm does not appear. Secondly, I was wondering how you would create a large textbox to store someone's biography.
Models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
biography = models.CharField(max_length = 255, default = '')
city = models.CharField(max_length=100, default = '')
website = models.URLField(default='')
image = models.ImageField(upload_to='profile_image', blank=True)
def setdefault(self, default_path='/profile_image/Default.jpg'):
if self.image:
return self.image
return default_path
def __str__(self):
return self.user.username
Forms.Py
class UpdateBioForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = (
'biography',
'city',
'website'
)
def save(self, commit=True):
savedBio = super(UpdateBioForm, self).save(commit=False)
savedBio.biography = self.cleaned_data['biography']
savedBio.city = self.cleaned_data['city']
savedBio.website = self.cleaned_data['website']
if commit:
savedBio.save()
return savedBio
Views.py
def update_bio(request):
if request.method == 'POST':
form = UpdateBioForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('/')
else:
form = UpdateBioForm(instance=request.user)
args = {'form':form}
return render(request, 'accounts/update_bio.html')
urls.py
url(r'^profile/updatebio/$',views.update_bio, name='update_bio'),
update_bio.html
{% extends 'base.html' %}
{% block body %}
<div class="container">
<h1>Update Biography</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
</div>
{% endblock %}
You are not passing any context to your render() method - you define args but don't do anything with that variable. Change it to:
args = {'form':form}
return render(request, 'accounts/update_bio.html', context=args) # <-- You're missing context