I have created small stock web app.
I created a stock model with unique part_number field. In my update template I send all item information to be displayed. Then I get an error in the part_number field that it is already there.
How can I avoid this validation for that part_number only?
I mean for same part_number suppose validation will not work. But if I modified to another part_number that already exists I get an error that it's being duplicated.
Model:
class Stock(models.Model):
part_number = models.CharField(max_length=30, blank=False, unique=True)
part_name = models.CharField(max_length=70)
quantity = models.IntegerField(blank=False)
location = models.CharField(max_length=3, blank=True)
model = models.CharField(max_length=40, blank=True, null=True, default="")
min_quantity = models.IntegerField(unique=False, blank=True, default=0)
max_quantity = models.IntegerField(unique=False, blank=True, default=0)
class Meta:
ordering = ['part_number']
def clean(self):
self.part_number = self.part_number.upper()
def __str__(self):
return self.part_number
Form.py:
class StockUpdateModelForm(forms.ModelForm):
class Meta:
model = models.Stock
fields = ['part_name', 'quantity', 'location','part_number']
views.py:
def stock_update_form_view(request, part_id):
item = Stock.objects.get(id=part_id)
item_id = Stock.objects.get(id=part_id).pk
form = StockUpdateModelForm({
'part_number' : item.part_number,
'part_name' : item.part_name,
'quantity' : item.quantity,
'location' : item.location
})
if request.method == 'POST':
form = StockUpdateModelForm(request.POST)
if form.is_valid():
s = Stock.objects.get(pk=item_id)
s.part_name = form.cleaned_data['part_name']
s.part_number = form.cleaned_data['part_number']
s.quantity = form.cleaned_data['quantity']
s.location = form.cleaned_data['location']
print("form is valid")
s.save()
return redirect('/stock/')
return render(request, 'stock/stock_update.html', {'form': form, 'pn': item.part_number})
html:
<form class="bg-light shadow" method="POST">
<div style="margin-left:10%; margin-top:30px">
<h4>Part Number : {{ pn }}</h4>
</div>
<hr style="width:100%">
{% csrf_token %}
<div class="row" style="margin-left:30px; margin-top:40px ">
<div class="col-sm-4" style="margin-left:6%">
{{ form.part_name|as_crispy_field }}
</div>
<div class="col-sm-4" style="margin-left:15%">
{{ form.part_number|as_crispy_field }}
</div>
<div class="col-sm-4" style="margin-left:6%">
{{ form.quantity|as_crispy_field }}
</div>
<div class="col-sm-4" style="margin-left:15%">
{{ form.location|as_crispy_field }}
</div>
<div class="col-sm-4" style="height: 100px; margin-top:30px ; margin-left:6%">
<hr style="width:100%">
<input class="btn btn-primary" type="submit" value="Save"
style="width: 150px;">
</div>
</div>
</form>
try this
if request.method == 'POST':
form = StockUpdateModelForm(request.POST, instance=item)
if form.is_valid():
form.save()
Related
The site has the ability to create a post for a specific game. When you try to create a post, it is created but the ManyToManyField remain empty. How to fix it?
forms.py
class AddPost(forms.ModelForm):
title = forms.CharField(label='Title', widget=forms.TextInput(attrs={'placeholder': 'Заголовок...'}),
help_text='Максимум 100 символів.')
games = forms.ModelChoiceField(queryset=Game.objects.filter(draft=False), widget=forms.Select, required=True)
tags = forms.ModelMultipleChoiceField(queryset=Tags.objects.all(), widget=forms.SelectMultiple(
attrs={'style': "padding: 10px; background:#edf2ff; border:none;"}))
foreword_description = forms.CharField(label='Small Description',
widget=forms.Textarea(attrs={'placeholder': 'Коротке описання...'}),
help_text='Максимум 335 символів.')
description = forms.CharField(label='Description', widget=CKEditorUploadingWidget())
rank = forms.FloatField(label='Rank', widget=forms.TextInput(attrs={'placeholder': 'Оцінка...'}))
good = forms.ModelChoiceField(queryset=Good.objects.all(), widget=forms.Select(
attrs={'style': "padding: 10px; background:#edf2ff; border:none;"}))
bad = forms.ModelChoiceField(queryset=Bad.objects.all(), widget=forms.Select(
attrs={'style': "padding: 10px; background:#edf2ff; border:none;"}))
url = forms.SlugField(label='Title', widget=forms.TextInput(attrs={'placeholder': 'Унікальний ідентифікатор...'}),
help_text='Максимум 255 символів.')
premiere = forms.DateField(label='Date', widget=forms.SelectDateWidget(attrs=({'style': 'width: 10%; display: inline-block;'})),
help_text='У форматі: 24.03.2022.')
class Meta:
model = Post
fields = (
'title', 'games', 'tags', "foreword_description", "description", "rank", "good", "bad", "url", "premiere",)
views.py
def addpost(request):
if request.method == "POST":
form = AddPost(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('../blogs/')
else:
form = AddPost()
data = {
'form': form,
'add': True
}
return render(request, 'gamelibs/user-post-manager.html', {'form': form})
models.py
class Game(models.Model):
title = models.CharField("Назва", max_length=100)
tagline = models.CharField("Слоган", max_length=500, default='')
description = models.TextField("Описання")
description_small = models.CharField("Описання коротко", max_length=100, null=True)
poster = models.ImageField("Постер", upload_to="games/poster/")
banner = models.ImageField("Банер", upload_to="games/banner/", null=True)
treiler = models.CharField("Трейлер", max_length=500, null=True)
treiler_img = models.ImageField("Інтро терейлеру", upload_to="games/intro/", null=True)
country = models.CharField("Країна", max_length=30)
company = models.ManyToManyField(Company, verbose_name="Компанія", related_name="company_game")
ganres = models.ManyToManyField(Ganre, verbose_name="Жанри")
price = models.FloatField("Ціна", help_text="У форматі 10.00", max_length=100)
sale_price = models.IntegerField('Скидка в процентах', blank=True, default=0)
world_premiere = models.DateField("Дата виходу", default=date.today)
budget = models.PositiveIntegerField("Бюджет", default=0, help_text="вказуйте сумму в доларах.")
category = models.ManyToManyField(Category, verbose_name="Категорія")
url = models.SlugField(max_length=255, unique=True)
os = models.CharField("Операційні системи", max_length=100)
processor = models.CharField("Процесор", max_length=100)
memory = models.CharField("Операційна памьять", max_length=100)
graphics = models.CharField("Відеокарта", max_length=100)
hard_drive = models.CharField("Місце на диску", max_length=100)
hit_count_generic = GenericRelation(HitCount, object_id_field='object_pk',
related_query_name='hit_count_generic_relation', default=0)
draft = models.BooleanField("Чернетка", default=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("game_details", kwargs={"slug": self.url})
def get_sale(self):
if self.sale_price == 100:
return 'FREE'
elif self.sale_price == 0:
return f'{self.price}'
else:
price = float(self.price * (100 - self.sale_price) / 100)
x = float('{:.2f}'.format(price))
return x
class Meta:
verbose_name = "Гра"
verbose_name_plural = "Ігри"
class Tags(models.Model):
title = models.CharField("Заголовок", max_length=100)
url = models.SlugField(max_length=160, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("tag_filter", kwargs={"slug": self.url})
class Meta:
verbose_name = "Тег"
verbose_name_plural = "Теги"
class Good(models.Model):
title = models.CharField("Заголовок", max_length=100)
url = models.SlugField(max_length=160, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("good_blog_filter", kwargs={"slug": self.url})
class Meta:
verbose_name = "Позитив"
verbose_name_plural = "Позитивні"
class Bad(models.Model):
title = models.CharField("Заголовок", max_length=100)
url = models.SlugField(max_length=160, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("bad_blog_filter", kwargs={"slug": self.url})
class Meta:
verbose_name = "Негатив"
verbose_name_plural = "Негативні"
class Post(models.Model):
title = models.CharField("Заголовок", max_length=100)
games = models.ManyToManyField(Game, verbose_name="Вкажіть гру", help_text="Вказати тільки одну гру!",
related_name='games')
tags = models.ManyToManyField(Tags, verbose_name="Теги", help_text="Вказати тільки 4 тега!")
foreword_description = models.TextField("Передмова", max_length=335)
description = models.TextField("Описання")
rank = models.FloatField("Оцінка", default=0, help_text="Від 1 до 10")
good = models.ManyToManyField(Good, verbose_name="Позитивні речі", help_text="Максимальна кількість 4")
bad = models.ManyToManyField(Bad, verbose_name="Негативні речі", help_text="Максимальна кількість 4")
premiere = models.DateField("Дата публікації", default=date.today)
url = models.SlugField(max_length=255, unique=True, default="Введіть унікальний аудентифікатор")
hit_count_generic = GenericRelation(HitCount, object_id_field='object_pk',
related_query_name='hit_count_generic_relation')
draft = models.BooleanField("Чернетка", default=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("post_details", kwargs={"slug": self.url})
class Meta:
verbose_name = "Пост"
verbose_name_plural = "Пости"
html
<form method="POST" enctype="multipart/form-data" name="filter-form">{% csrf_token %}
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Заголовок:</label>
<div class="col-sm-10">
<div class="youplay-input">
{{ form.title }}
</div>
<h6><i class="fa fa-circle-exclamation"> {{ form.title.help_text }}</i></h6>
{{ form.title.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="new_password">Оберіть гру:</label>
<div class="col-sm-10">
<div class=" col-sm-10
field-games">
<div class="related-widget-wrapper">
{{ form.games }}
{{ form.games.errors }}
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="new_password">Оберіть теги:</label>
<div class="col-sm-10">
{{ form.tags }}
{{ form.tags.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Коротке описання:</label>
<div class="col-sm-10">
<div class="youplay-input">
{{ form.foreword_description }}
</div>
<h6><i class="fa fa-circle-exclamation"> {{ form.foreword_description.help_text }}</i></h6>
{{ form.foreword_description.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Описання:</label>
<div class="col-sm-10">
{{ form.description }}
{{ form.description.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Оцінка гри:</label>
<div class="col-sm-10">
<div class="youplay-input">
{{ form.rank }}
</div>
{{ form.rank.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="new_password">Позитивні речі:</label>
<div class="col-sm-10">
{{ form.good }}
{{ form.good.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="new_password">Негативні речі:</label>
<div class="col-sm-10">
{{ form.bad }}
{{ form.bad.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">URL:</label>
<div class="col-sm-10">
<div class="youplay-input">
{{ form.url }}
</div>
<h6><i class="fa fa-circle-exclamation"> {{ form.url.help_text }}</i></h6>
{{ form.url.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Дата:</label>
<div class="col-sm-10">
{{ form.premiere }}
<h6><i class="fa fa-circle-exclamation"> {{ form.premiere.help_text }}</i></h6>
{{ form.premiere.errors }}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Створити Пост</button>
</div>
</div>
</form>
What am I doing wrong or how else can I implement this? I just don't fully understand why the form is saved, but the ModelChoiceField fields are empty, why? I will be grateful for your answers
There is a disconnect between your many-to-many fields and your form.
Let's take 'game'. In your model it's a many-to-many field. But in your form it's a ModelChoiceField. A ModelChoiceField should link to a field that has a Foreignkey relationship (many to one), not a many to many. So, in this case, your model is saying a post can be about many different games, but your form only allowing the user to select one. With a one to many, you can still have many posts (plural) referring to the same game, but each individual post can only refer to one.
If you want the user to be able to select multiple games for each post, then the form should have a ModelMultipleChoiceField. If you only want a post to be about one game, then the model should have a ForiegnKey (one-to-many) rather than a many-to-many relationship. Then the form and the model will align and handle each other appropriately.
I am trying to save a modelform by prepopulating 'template_name' field . As per django documentation and other threads it is clear that initial parameter should work but i just can't make it work for my code. I am getting the error that template_name field is empty. Any help on what am I missing and any other approach towards this will be great. Here is the code
models.py
class TemplateNameModel(models.Model):
"Model to add the template name"
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
tna_template_name = models.CharField(verbose_name="Template name",max_length = 128, unique = True,
null = False, blank = False, help_text="please enter name of the new tna template")
description = models.CharField(verbose_name="template description", max_length = 256,
null = True, blank = True, help_text ="Please enter the description(optional)")
created_by = models.TextField(verbose_name="Template created by", max_length= 128,
null = False, blank = False,help_text ="Please enter the name of creator")
date_created = models.DateTimeField(auto_created= True, null = True, blank = True)
is_active = models.BooleanField(verbose_name="Template status",null = False , blank= False)
def __str__(self):
return self.tna_template_name
class TnaTemplateModel(models.Model):
id = models.AutoField(primary_key=True, editable=False)
template_name = models.ForeignKey(TemplateNameModel, verbose_name="template name", null=False,
blank=False, on_delete=models.CASCADE, help_text="Select the template")
process_name = models.ForeignKey(ProcessModel, verbose_name="process name", null=False,
blank=False, on_delete=models.CASCADE, help_text="Select the process")
sequence = models.IntegerField(verbose_name="Process Sequence",null = False,blank = False)
is_base = models.BooleanField()
formula = models.IntegerField(verbose_name="Formula", null= True,blank = True)
remarks = models.CharField(verbose_name="Process remarks", null= True, blank = True,max_length= 300)
class Meta:
unique_together = ["template_name", "process_name"]
def __str__(self):
return str(self.template_name)
forms.py
class ProcessModelformNew(forms.ModelForm):
class Meta:
model = TnaTemplateModel
fields =('__all__')
views.py
def processcreatenew(request,pk):
template_name = TemplateNameModel.objects.get(id=pk)
if request.method == 'POST':
form = ProcessModelformNew(request.POST)
if form.is_valid():
form.save()
else:
data = {'template_name': template_name}
form = ProcessModelformNew(initial= data)
return render (request,"tna/template_tna/baseprocessmodel_create.html",{'form':form})
Html template
<form role="form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="card-body">
<div class="row">
<div class="col-md-6 col-sm-12">
<!-- text input -->
<div class="form-group">
{{form.process_name|as_crispy_field}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-12">
<!-- text input -->
<div class="form-group">
{{form.sequence|as_crispy_field}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-12">
<!-- text input -->
<div class="form-group">
{{form.is_base|as_crispy_field}}
</div>
</div>
<div class="col-md-6 col-sm-12">
<!-- text input -->
<div class="form-group">
{{form.formula|as_crispy_field}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-12">
<!-- text input -->
<div class="form-group">
{{form.remarks|as_crispy_field}}
</div>
</div>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
You need to render the template_name field in your template so the selected value is passed in the POST data.
{{ form.template_name }}
I suspect you do not want to display the field, you should override it's widget with forms.HiddenInput so that it is not visible to the user
class ProcessModelformNew(forms.ModelForm):
class Meta:
model = TnaTemplateModel
fields = '__all__'
widgets = {'template_name': forms.HiddenInput()}
First method
Include {{ form.template_name }} in your HTML even though you're not want to edit it, just make it hidden
Second method
In your forms.py instead of fields =('__all__') you can put exclude = ['template_name'] so it will no longer required, then in views.py
obj = form.save(commit=False)
obj.template_name = template_name
obj.save()
So if you don't want to include template_name in HTML the second method is good to go, also you don't have to initiate the form
forms.py
def __init__(self, *args, **kwargs):
template_name = kwargs.pop('template_name',None)
self.fields['template_name']= template_name
views.py
inside your model form
def processcreatenew(request,pk):
template_name = TemplateNameModel.objects.get(id=pk)
if request.method == 'POST':
form = ProcessModelformNew(request.POST or None, template_name= template_name)
Something like this you have to perform
My models:
class Comment(models.Model):
product = models.ForeignKey(Product ,on_delete=models.CASCADE, related_name='comments')
user = models.ForeignKey(User ,on_delete=models.CASCADE, max_length=80, related_name='comments_user')
body = models.TextField()
created_on = jmodels.jDateField(auto_now_add=True)
created_on_time = models.TimeField(auto_now_add=True,null=True)
active = models.BooleanField(default=False)
class Meta:
ordering = ['created_on']
def __str__(self):
return 'Comment {} by {}'.format(self.body, self.user)
class Rating(models.Model):
product = models.ForeignKey(Product ,on_delete=models.CASCADE)
user = models.ForeignKey(User ,on_delete=models.CASCADE)
score = models.IntegerField(default=0,
validators=[
MaxValueValidator(5),
MinValueValidator(0),
]
)
def __str__(self):
return 'rate {} by {} for {}'.format(self.score, self.user, self.product)
In product single page, I have comments part that I want show user rating if that user put comment in next of username and comment date.
My views :
def product_details(request, category_url, subcategory_url, product_url):
product = get_object_or_404(Product, product_url=product_url)
stocks = Stock.objects.filter(product=product)
rate = Rating.objects.filter(product=product, user=request.user)
all_rates = Rating.objects.filter(product=product)
all_rate_count = Rating.objects.filter(product=product).count()
all_rate = sum([all_rate.score for all_rate in all_rates])
all_rate = all_rate/all_rate_count
all_rate = all_rate*100/5
comments = product.comments.filter(product=product, active=True)
if request.method == "POST":
body = request.POST['body']
new_comment = Comment(user=request.user,product=product, body=body)
new_comment.save()
message_good = "نظر شما با موفقیت ثبت شد بعد از برسی نمایش داده میشود!"
ctx = {'product':product, 'stocks':stocks, 'rate':rate, 'all_rate':all_rate,
'comments':comments,
'message_good':message_good,
'all_rate_count':all_rate_count}
return render(request, 'products/product_details.html', ctx)
ctx = {'product':product, 'stocks':stocks, 'rate':rate, 'all_rate':all_rate,
'comments':comments,
'all_rate_count':all_rate_count}
return render(request, 'products/product_details.html', ctx)
And my html :
{% for comment in comments %}
<div class="comments" style="padding: 10px;">
<p class="font-weight-bold">
{{ comment.user }}
<span class=" text-muted font-weight-normal">
{{ comment.created_on }}
</span>
<span class=" text-muted font-weight-normal">
{{ comment.created_on_time|date:"G:i" }}
</span>
</p>
{{ comment.body | linebreaks }}
</div>
{% endfor %}
I updated my codes, and showed my views and my single html
so if please can help me about showing product rate by user for each comment that filtered by user.
or any better suggestion for other ways about rating or showing comments for single product page. thanks for helping
I would add a unique_together constraint to enforce that a user can only leave a single rating for a product.
class Rating(models.Model):
product = models.ForeignKey(Product ,on_delete=models.CASCADE)
user = models.ForeignKey(User ,on_delete=models.CASCADE)
score = models.IntegerField(default=0,
validators=[
MaxValueValidator(5),
MinValueValidator(0),
]
)
class Meta:
unique_together = ('product', 'user')
def __str__(self):
return 'rate {} by {} for {}'.format(self.score, self.user, self.product)
In your views, since you will only have one rating for a product per user.
rate = Rating.objects.get(product=product, user=request.user)
In your templates:
{% for comment in comments %}
<div class="comments" style="padding: 10px;">
<p class="font-weight-bold">
{{ comment.user }}
<span class=" text-muted font-weight-normal">
{{ comment.created_on }}
</span>
<span class=" text-muted font-weight-normal">
{{ comment.created_on_time|date:"G:i" }}
</span>
</p>
{{ comment.body | linebreaks }}
{{ rate.score }}
</div>
{% endfor %}
I have a date of birth field in my model but why it's not showing up in the template when I render it? The date_of_birth is inside Teacher model. And Do you have any good idea on date_of_birth field? Because right now I'm using charfield for that so I need to convert the DateInput to string so that I can add it into charfield.
here is my models.py
class Teacher(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE, primary_key=True)
date_of_birth = models.CharField(max_length=100)
teacher_type = models.CharField(max_length=50
def __str__(self):
return self.user.email
my forms.py
class TeacherRegisterForm(UserCreationForm):
date_attr = {'class': 'form-control', 'id': 'dateofbirth-register', 'type': 'date'}
date_of_birth = forms.DateField(widget = forms.DateInput(attrs=date_attr))
teacher_type = forms.ChoiceField(label=_('Teacher Type'), choices=type_choice
class Meta(UserCreationForm):
model = CustomUser
fields = ['date_of_birth', 'teacher_type']
def save(self, commit=True):
user = super().save(commit=False)
user.is_teacher = True
user.save()
teacher = Teacher.objects.create(user=user)
teacher.date_of_birth += str(self.cleaned_data.get('date_of_birth'))
teacher.teacher_type += self.cleaned_data.get('teacher_type')
return user
views.py
#login_required
#teacher_required
def teacherInfoView(request):
template_name = "attendance/content/teacher/teacher_info.html"
teacher_info = Teacher.objects.filter(user=request.user)
context = {'teacher_info': teacher_info}
return render(request, template_name, context)
template
{% for info in teacher_info %}
<!-- firstname -->
<div class="row">
<div class="ml-5 mr-auto">
<h5>Name : {{ info.user.first_name }} {{ info.user.last_name }}</h5>
</div>
<div class="ml-5">
<h5>Email : {{ info.user.email }}</h5>
</div>
</div>
<div class="row">
<div class="ml-5">
<h5>Date Of Birth : {{ info.date_of_birth }}</h5>
</div>
<div class="ml-5">
<h5>Gender : {{ info.user.gender }}</h5>
</div>
</div>
{% endfor %}
I'm getting an issue with my Django form validation. I would like to display form errors and make all fields required. I don't know why my fields can accept blank while blank is not defined in my model file.
This is my model :
class Customer(models.Model):
email = models.CharField(max_length=150, verbose_name=_('e-mail'), null=False)
first_name = models.CharField(max_length=70, verbose_name=_('first name'), null=False)
last_name = models.CharField(max_length=70, verbose_name=_('last name'), null=False)
country = models.ForeignKey(Country, verbose_name=_('country'))
institution = models.CharField(max_length=255, verbose_name=_('institution'), null=True)
creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('creation date'), null=False)
modification_date = models.DateTimeField(auto_now=True, verbose_name=_('modification date'), null=False)
class Meta:
verbose_name = _('customer')
verbose_name_plural = _('customer')
def __str__(self):
return f"{self.email}"
This is my form :
class CustomerForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(CustomerForm, self).__init__(*args, **kwargs)
self.fields['country'].empty_label = _('Select a country')
self.fields['country'].queryset = self.fields['country'].queryset.order_by(
'name')
for key in self.fields:
self.fields[key].required = True
class Meta:
model = Customer
fields = ['email', 'first_name', 'last_name', 'country', 'institution']
widgets = {
'email': forms.TextInput(attrs={'placeholder': _('name#example.com')}),
'first_name': forms.TextInput(attrs={'placeholder': _('First Name')}),
'last_name': forms.TextInput(attrs={'placeholder': _('Last Name')}),
'institution': forms.TextInput(attrs={'placeholder': _('Agency, company, academic or other affiliation')}),
}
You can find here my view with Django CBV :
class HomeView(CreateView):
""" Render the home page """
template_name = 'app/index.html'
form_class = CustomerForm
def get_context_data(self, **kwargs):
kwargs['document_list'] = Document.objects.all().order_by('publication__category__name')
return super(HomeView, self).get_context_data(**kwargs)
def post(self, request, *args, **kwargs):
if request.method != 'POST':
return HttpResponseRedirect(self.get_success_url())
form = self.form_class(request.POST)
email = request.POST['email']
country_id = request.POST['country']
country = Country.objects.get(id=country_id)
for checkbox in request.POST.getlist('DocumentChoice'):
document = Document.objects.get(id=checkbox)
token = self.gen_token(email, document.edqm_id)
Download.objects.create(email=email, country=country, pub_id=checkbox, token=token,
expiration_date=now + timedelta(minutes=10))
if not form.is_valid():
print('form invalid')
continue
return HttpResponseRedirect(self.get_success_url())
And finally my template :
{% extends "publication/base_backend.html" %}
{% load staticfiles %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block main %}
<form method="post" id="customerform" novalidate>
{% csrf_token %}
<h3>{% trans 'Your information' %}</h3>
<hr>
<div class="col-sm-12 col-md-12 col-lg-12">
{{ form.email|as_crispy_field:"bootstrap" }}
</div>
<br />
<br />
<br />
<br />
<div class="alert alert-info col-sm-12 col-md-12 col-lg-12" role="alert">
<small>{% trans "The fields below are optional if you have already requested a publication:" %}</small>
</div>
<div class="col-sm-5 col-md-5 col-lg-5">
{{ form.first_name|as_crispy_field:"bootstrap" }}<br>
{{ form.country|as_crispy_field:"bootstrap" }}
</div>
<div class="col-sm-5 col-md-5 col-lg-5 col-sm-offset-2 col-md-offset-2 col-lg-offset-2">
{{ form.last_name|as_crispy_field:"bootstrap" }}<br>
{{ form.institution|as_crispy_field:"bootstrap" }}
</div>
<div class="col-md-12">
<br />
<br />
</div>
<input type="submit" class="btn btn-default" value="{% trans 'Save' %}"/>
{% trans 'Cancel' %}
</form>
Issues :
According to required fields, I don't know why my form doesn't display missing values errors when I want to submit it.
I have to display fields as shown in my template because I have to make bootstrap design.
In order to display form errors, I have to write {{form.email.errors}} for example but nothing appears.
Thank you by advance