Django Forms - how to add the + sign for a Many2Many field - django

enter image description hereRelated to Django Forms and Many2Many
I have tried to look for ways to add the + to my django form when I want to add a new post to my webpage.
What I'm looking for is a similar function as the one in admin module. See picture.
I have tried to read though the docs but not sure what to look for. Have anybody build something similar?
my model looks like this
class Wine_taste(models.Model):
title = models.CharField(max_length=128, null=True, blank=True)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
category = models.ManyToManyField('Wine_Category', verbose_name='Kind of Wine',related_name='wcategory')
subcategory = models.ForeignKey('Wine_SubCategory', verbose_name='Wine type',on_delete=models.SET_NULL, null=True, blank=True)
review = models.TextField()
producer_taste = models.ForeignKey('Wine_Producer', verbose_name='Producer or shipper', on_delete=models.SET_NULL, null=True, blank=True )
grape_taste = models.ManyToManyField('Wine_Grapes', verbose_name='Grapes')
country_taste = models.ForeignKey('Wine_Country', verbose_name='Country of origin', on_delete=models.SET_NULL, null=True, blank=True )
sweetness = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate Sweetness')
acid = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate acid level')
fruit = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate fruitness')
taste = models.PositiveSmallIntegerField(choices=RATE_CHOICES, verbose_name='Rate taste')
overall = models.PositiveSmallIntegerField(choices=RATE_CHOICES, verbose_name='Overall rate')
thumbnail = models.ImageField()
timestamp = models.DateTimeField(auto_now_add=True)
featured = models.BooleanField()
previous_post = models.ForeignKey('self', related_name='previous', on_delete=models.SET_NULL, null=True, blank=True)
next_post = models.ForeignKey('self', related_name='next', on_delete=models.SET_NULL, null=True, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('wine:wine-dyn', kwargs={"id": self.id})
def get_update_url(self):
return reverse('wine:wine-update', kwargs={"id": self.id})
def get_delete_url(self):
return reverse('wine:wine-delete', kwargs={"id": self.id})
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.thumbnail.path)
if img.height > 400:
new_height = 400
new_width = new_height / img.height * img.width
output_size = ((new_height, new_width))
img.thumbnail(output_size)
img.save(self.thumbnail.path)
#property
def get_comments(self):
return self.comments.all().order_by('-timestamp')
#property
def comment_count(self):
return Comment.objects.filter(post=self).count()
#property
def view_count(self):
return PostView.objects.filter(post=self).count()
Blockquote
this is my view:
def wine_detailed_create(request):
title = 'Create'
form = CreateForm(request.POST or None, request.FILES or None)
author = get_author(request.user)
if request.method == 'POST':
if form.is_valid():
form.instance.author = author
form.save()
return redirect (reverse('wine:wine-dyn', kwargs={'id': form.instance.id}))
context = {
'title': title,
'form': form
}
return render(request, 'wine/wine_create.html', context)
and my forms:
class CreateForm(forms.ModelForm):
class Meta:
model = Wine_taste
fields = ('title',
'country_taste',
'category',
'subcategory',
'producer_taste',
'grape_taste',
'review',
'thumbnail',
'sweetness',
'acid',
'fruit',
'taste',
'overall',
'featured',
'previous_post',
'next_post',)
Blockquote
br
Lars

Related

Render all products that relate to one of subcategories of one category, in category page

I had a question. I am creating an ecommerce website in django. There, I have categories and subcategories. When I enter to subcategory page, I able to render all products that relate to this subcategory. But, when I wanted to render all product that relate on one parent category, I am having troubles. So, I have some subcategories in one category. In that category page, I want to render all products that relate to one of subcategories of this category. Can you help me please?
models.py
class Category(models.Model):
parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, blank=True, null=True)
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
ordering = models.IntegerField(default=0)
is_featured = models.BooleanField(default=False)
class Meta:
verbose_name_plural = 'Categories'
ordering = ('ordering',)
def __str__(self):
if self.parent is not None:
return f"{self.parent}/{self.title}"
return self.title
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
def get_absolute_url(self):
return '/%s/' % (self.slug)
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
parent = models.ForeignKey('self', related_name='variants', on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=200, verbose_name="Название продукта")
price = models.IntegerField(verbose_name="Цена")
slug = models.SlugField(max_length=255)
description = models.CharField(max_length=5000,blank=True, verbose_name="Описание:")
image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
novinki = models.BooleanField(default=False, verbose_name="Новинки")
popularnye = models.BooleanField(default=False, verbose_name="Популарные")
def __str__(self):
return self.name
class Meta:
verbose_name = 'Продукты'
verbose_name_plural = "Продукты"
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
views.py
def category_detail(request, slug):
data = cartData(request)
cartItems = data['cartItems']
order = data['order']
items = data['items']
categories_for_menu = Category.objects.filter(parent=None)[:3]
categories = Category.objects.filter(parent=None)
category = get_object_or_404(Category, slug=slug)
**products_all = Product.objects.filter(category.parent==category)**
print(products_all)
products = category.products.all()
context = {'items' : items, 'order' : order, 'cartItems' : cartItems, 'products':products, 'category':category, 'categories':categories,'categories_for_menu':categories_for_menu,'products_all':products_all}
return render(request, "store/categories.html", context)
Here I want to save all products that relate the category in products_all. Looking forward to your help!
class Category(models.Model):
# ...
root = models.ForeignKey('self', on_delete=models.CASCADE)
# ...
def save(self, *args, **kwargs):
self.root = self.parent.root if self.parent else self
# I didn't debug it. Maybe it has some bug.
super(Category, self).save(*args, **kwargs)
# query
Product.objects.filter(category__root=(...))
I don't agree this answer:
products = Product.objects.filter(Q(category = category)|Q(category__parent = category))
When your category is more than 2 depth, it will be wrong.
You can do it using Q function:
from django.db.models import Q
category = get_object_or_404(Category, slug=slug)
products = Product.objects.filter(Q(category = category)|Q(category__parent = category))

Adding a comment section form to my Django app

I get 2 different errors the first one is
Django Model IntegrityError: NOT NULL constraint failed:
I checked the solution for this, people said I've to make my FK attributes null = true and blank = true
so this solved that.
The second error I got after that was in my views.py
'CommentForm' object has no attribute 'cleaned_data'
My Views.py file:
def project(request, pk):
form = CommentForm()
project = ProjectModel.objects.get(id=pk)
contextt ={
"project": project,
"form":form,
}
if request.method == "POST":
form.save()
return redirect(request, "/dashboard")
else:
return render(request, "projects.html", contextt)
and my Models.py:
class ProjectModel(models.Model):
caption = models.CharField(max_length=100)
video = models.FileField(upload_to="video/%y", validators=[file_size])
ProjectName = models.CharField(max_length=50, )
ProjectDescription = models.TextField(max_length=1000,)
Project_Background_picture = models.ImageField(
upload_to=settings.MEDIA_ROOT, default='/static/img/default.png')
Approved = models.BooleanField(default=False)
Finished = models.BooleanField(default=False)
Goal = models.DecimalField(
decimal_places=3, max_digits=6, blank=True, null=True)
Pledges = models.DecimalField(
decimal_places=3, max_digits=6, blank=True, null=True)
Number_of_investors = models.IntegerField(blank=True, null=True)
FirstReward = models.TextField(max_length=1000, default=' 10$ ')
SecondReward = models.TextField(max_length=1000, default=' 25$')
ThirdReward = models.TextField(max_length=1000, default='50$')
FourthReward = models.TextField(max_length=1000, default='100$ +s')
def __str__(self):
return self.caption
class comment(models.Model):
ProjectModel = models.ForeignKey(
ProjectModel, related_name='comments', on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=255)
CommentBody = models.TextField(default='comment here!', max_length=1000 )
date_added = models.DateTimeField(auto_now_add=True)
def _str_(self):
return '%s - %s' % (self.ProjectModel.caption, self.name)
try this:
def project(request, pk):
form = CommentForm()
project = ProjectModel.objects.get(id=pk)
contextt ={
"project": project,
"form ":form ,
}
if request.method == 'POST' :
form = CommentForm(data=request.POST)
if form.is_valid():
form= form.save(commit=False) #new line
form.ProjectModel = project #new line
form.save()
return redirect("/dashboard")
else:
return render(request, "projects.html", contextt)

auto populate slug field is not working in django

I am trying to make posts which uses slug as post url. I add slug field But its not auto populating. I want to make it auto populate.
So far I have done this. I add pre_save at the end.
I tried to save posts from django admin it says something like this
This field is required.
posts/models.py
from django.db import models
from django.core.validators import FileExtensionValidator
from django.db.models.signals import pre_save
from django.utils.text import slugify
# Create your models here.
class Category(models.Model):
title = models.CharField(max_length = 120, verbose_name="Title" )
updated_at = models.DateTimeField(auto_now_add=True, verbose_name="Updated at")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
ordering = ['title']
def __str__(self):
return self.title
class Posts(models.Model):
title = models.CharField(max_length=60)
slug = models.SlugField(unique = True)
file_upload = models.FileField(null= True, blank=True, validators=[FileExtensionValidator(['pdf'])])
content = models.TextField()
category = models.ForeignKey(Category, null= True,verbose_name="Category", on_delete=models.CASCADE)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
# class Meta:
# verbose_name = "Post"
# verbose_name_plural = "Posts"
# ordering = ['-created_at']
def __unicode__(self):
return self.title
def __str__(self):
return self.title
def create_slug(instance, new_slug=None):
slug = slugify(instance.title, allow_unicode = True)
if new_slug is not None:
slug = new_slug
qs = Posts.objects.filter(slug=slug).order_by("-id")
exists = qs.exists()
if exists:
new_slug = "%s-%s"%(slug, qs.first().id)
return create_slug(instance, new_slug=new_slug)
return slug
def pre_save_post_receiver( instance, sender,*args, **kwargs):
if not instance.slug:
instance.slug = create_slug(instance)
pre_save.connect(pre_save_post_receiver, sender=Posts)
You can use django-slugger
And then to add this to admin add
admin.py
prepopulated_fields = {'slug': ('title',), }
As from your code instance.title is always important to generate slug value. Then one of possible way without triggering pre_save signal is to overwrite the model save function and assign your value there.
def create_slug(title, new_slug=None):
slug = slugify(title, allow_unicode = True)
if new_slug is not None:
slug = new_slug
qs = Posts.objects.filter(slug=slug).order_by("-id")
exists = qs.exists()
if exists:
new_slug = "%s-%s"%(slug, qs.first().id)
return create_slug(title, new_slug=new_slug)
return slug
class Posts(models.Model):
title = models.CharField(max_length=60)
slug = models.SlugField(unique = True)
file_upload = models.FileField(null= True, blank=True, validators=[FileExtensionValidator(['pdf'])])
content = models.TextField()
category = models.ForeignKey(Category, null= True,verbose_name="Category", on_delete=models.CASCADE)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
# class Meta:
# verbose_name = "Post"
# verbose_name_plural = "Posts"
# ordering = ['-created_at']
def save(self, *args, **kwargs):
if not self.slug:
self.slug = create_slug(self.title)
return super(Posts, self).save(*args, **kwargs) # important to call this
def __unicode__(self):
return self.title
def __str__(self):
return self.title
I am really hope this solution should work. Another possible way to use field default callable function link but from your code i can see that title is also important. I am not fully sure but following thing also can work.
def create_slug(title, new_slug=None):
slug = slugify(title, allow_unicode = True)
if new_slug is not None:
slug = new_slug
qs = Posts.objects.filter(slug=slug).order_by("-id")
exists = qs.exists()
if exists:
new_slug = "%s-%s"%(slug, qs.first().id)
return create_slug(title, new_slug=new_slug)
return slug
class Posts(models.Model):
title = models.CharField(max_length=60)
slug = models.SlugField(unique = True, default=create_slug(self.title))
file_upload = models.FileField(null= True, blank=True, validators=[FileExtensionValidator(['pdf'])])
content = models.TextField()
category = models.ForeignKey(Category, null= True,verbose_name="Category", on_delete=models.CASCADE)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
# class Meta:
# verbose_name = "Post"
# verbose_name_plural = "Posts"
# ordering = ['-created_at']
def __unicode__(self):
return self.title
def __str__(self):
return self.title

KeyError at /partners/create/ 'name'

I have a model Partner that is related to Product by a one to many relationships. I am using inlineformsets for the Product and I am gettig the following error which I don't understand:"KeyError at /partners/create/ 'name'"
my views are as follows:
def partner_create(request):
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
ProductFormSet = inlineformset_factory(Partner, Product, form=ProductForm, extra=3, min_num=1)
if request.method == 'POST':
partnerForm = PartnerForm(request.POST or None, request.FILES or None)
formset = ProductFormSet(request.POST, request.FILES, queryset=Product.objects.none())
if partnerForm.is_valid() and formset.is_valid():
instance = partnerForm.save(commit=False)
instance.save()
for form in formset.cleaned_data:
name = form["name"]
description = form["description"]
price = form["price"]
image = form["image"]
product = Product(partner=instance, name=name, description=description, price=price, product_image=image)
product.save()
messages.success(request, "Partner Successfully Created")
else:
print partnerForm.errors, formset.errors
else:
partnerForm = PartnerForm()
formset = ProductFormSet(queryset=Product.objects.none())
return render(request, "partner_form.html", {"partnerForm": partnerForm, "formset": formset})
my forms.py are as follows:
class PartnerForm(forms.ModelForm):
mission = forms.CharField(widget=PagedownWidget(show_preview=False))
vision = forms.CharField(widget=PagedownWidget(show_preview=False))
# publish = forms.DateField(widget=forms.SelectDateWidget)
class Meta:
model = Partner
fields = [
"name",
"logo",
"banner_image",
"mission",
"vision",
"website_link",
"fb_link",
"twitter_link",
"ig_link",
]
class ProductForm(forms.ModelForm):
image = forms.ImageField(label='Image')
class Meta:
model = Product
fields = [
"partner",
"name",
"description",
"price",
"image",
]
My models.py are as follows:
def upload_location(instance, filename):
#filebase, extension = filename.split(".")
# return "%s/%s" %(instance.name, instance.id)
PartnerModel = instance.__class__
exists = PartnerModel.objects.exists()
if exists:
new_id = PartnerModel.objects.order_by("id").last().id + 1
else:
new_id = 1
file_name, file_extension = filename.split('.')
return "%s/%s/%s-%s.%s" %('partner',instance.name, file_name, new_id, file_extension)
class Partner(models.Model):
name = models.CharField(max_length=120)
logo = models.ImageField(upload_to=upload_location,
null=True,
blank=True,
width_field="width_field",
height_field="height_field")
banner_image = models.ImageField(upload_to=upload_location,
null=True,
blank=True,
width_field="width_field",
height_field="height_field")
mission = models.TextField()
vision = models.TextField()
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
# text = models.TextField()
website_link = models.CharField(max_length=120)
fb_link = models.CharField(max_length=120)
twitter_link = models.CharField(max_length=120)
ig_link = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return reverse("partners:detail", kwargs={"slug": self.slug})
# return "/partner/%s/" %(self.id)
def get_markdown(self):
mission = self.mission
markdown_text = markdown(mission)
return mark_safe(markdown_text)
#Creating a many to one relationship so that one can upload many Products
class Product(models.Model):
partner = models.ForeignKey(Partner, default=None)
name = models.CharField(max_length=120)
product_image = models.ImageField(upload_to=upload_location,
# product_image = models.ImageField(upload_to= (upload_location + '/' + name), Something like this need to append actual product name so these dont just get dumped in the media for partners
null=True,
blank=True,
width_field="width_field",
height_field="height_field",
verbose_name='Image',)
description = models.TextField()
price = models.DecimalField(max_digits=6, decimal_places=2, null=True)
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
def __unicode__(self): # __unicode__ on Python 2
return self.name
I would really like to understand what is going on as well as how to fix it or a hint in the right direction. Thank you in advance for your help!
To find out why you're getting the error, you should add some printing or logging to your code. What is the value of formset.cleaned_data? Is it what you think it should be?
There's a simpler approach that looping through the formset's cleaned_data. The docs show how to save a formset. You can save with commit=False, then set the partner field before saving to the database.
products = formset.save(commit=False)
for product in products:
product.partner=instance
product.save()
Note that if you do this, you should probably switch to a modelformset_factory instead of inlineformset_factory, and remove partner from the list of the fields of the ProductForm.
The formset form save method seems incorrect, use something like
for form in formset.cleaned_data:
if form.is_valid():
name = form.cleaned_data.get("name")
description = form.cleaned_data.get("description")
price = form.cleaned_data.get("price")
image = form.cleaned_data.get("image")
Please lemme know if this works :)

Django Form: form with ForeignKey

I'm making online shopping mall using Django(1.9.7) framework.
I think that showing codes is much easier than explaining in text.
models.py
class Product(TimeStampedModel):
name = models.CharField(max_length=120, unique=True)
slug = models.SlugField(null=True, blank=True)
description = models.TextField(max_length=400, blank=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Variation(TimeStampedModel):
COLOR_CHOICES = (
('black', '흑백'),
('single', '단색'),
('multi', '컬러'),
)
price = models.DecimalField(
decimal_places=0,
max_digits=15,
blank=True,
null=True,
)
product = models.ForeignKey(Product)
color = models.CharField(
max_length=10,
choices=COLOR_CHOICES,
)
is_active = models.BooleanField(default=True)
class Meta:
unique_together = (('product', 'color'))
def __str__(self):
return str(self.product) + ' - ' + self.get_color_display()
I create form in my product_detail view and pass it as context data to template.
views.py
class ProductDetailView(DetailView):
model = Product
context_object_name = "product"
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
product = self.get_object()
context['cartitem_form'] = CartItemForm(product)
return context
What I want to do through form:
I want to show variations only related with given product. So I pass product as argument of form in view and save this product. And I'm trying to set the variation queryset through ModelChoiceField:
class CartItemForm(forms.ModelForm):
variation = forms.ModelChoiceField(
queryset=Variation.objects.filter(product=self.product)
)
class Meta:
model = CartItem
fields = (
'variation',
'width',
'height',
'quantity',
)
def __init__(self, *args, **kwargs):
self.product = kwargs.pop('product')
super().__init__(*args, **kwargs)
def save(self):
cart_item = super().save(commit=False)
cart_item.save()
return cart_item
but it doesn't work. How can I implement this?