I have created two models w_orders(workorders) and tobjects. I have two templates, one is only for creating a workorder and this works fine and one other template which contains data of both workorders and objects. tobjects is related to the table w_orders and I want to be able to create x number of objects for a workorder. For every workorder an object is created automatically. So far I have created the template and I can't quite figure how to display only the related objects for a certain workorder. For example for workorder no 1 I get the objects that are created for other workorders. As well I cannot add or edit an object related to the workorder. This is my code:
models.py
class w_orders(models.Model):
Id = models.BigAutoField(primary_key=True)
datedefwo = models.DateField(default=datetime.now)
datesched = models.DateField(blank=True, null=True)
datefinished = models.DateField(blank=True, null=True)
sign = models.BigIntegerField(blank=True, null=True)
statusid = models.BigIntegerField(blank=True, null=True, default=1, choices=STATUS_CHOICES)
typeid = models.BigIntegerField(blank=True, null=True, default=1, choices=TYPE_CHOICES)
comments = models.CharField(max_length=254, blank=True, null=True)
navid = models.BigIntegerField(blank=True, null=True)
navkonsid = models.CharField(max_length=12, blank=True, null=True)
navname = models.CharField(max_length=254, blank=True, null=True)
navcustadr = models.CharField(max_length=254, blank=True, null=True)
navdebt = models.FloatField(blank=True, null=True)
navpropcode = models.CharField(max_length=254, blank=True, null=True)
navdepcode = models.CharField(max_length=254, blank=True, null=True)
navphoneno = models.CharField(max_length=254, blank=True, null=True)
navreasoncomp = models.CharField(max_length=254, blank=True, null=True)
nightshift = models.BooleanField(default=False)
priority = models.BigIntegerField(blank=True, null=True)
stid = models.BigIntegerField(blank=True, null=True)
mapurl = models.CharField(max_length=254, blank=True, null=True)
def __unicode__(self):
return self.Id
class tobjects(models.Model):
oid = models.BigAutoField(primary_key=True)
wid = models.ForeignKey(w_orders, on_delete=models.CASCADE)
objtypegisid = models.BigIntegerField(blank=True, null=True, default=1)
objgisid = models.BigIntegerField(blank=True, null=True, default=1)
condgenid = models.BigIntegerField(blank=True, null=True, default=1)
condriskid = models.BigIntegerField(blank=True, null=True, default=1)
condratsid = models.BigIntegerField(blank=True, null=True, default=1)
condmhcoverid = models.BigIntegerField(blank=True, null=True, default=1)
condmhwallid = models.BigIntegerField(blank=True, null=True, default=1)
condpipehydrsid = models.BigIntegerField(blank=True, null=True, default=1)
condpipehydreid = models.BigIntegerField(blank=True, null=True, default=1)
condpipedepvolsid = models.BigIntegerField(blank=True, null=True, default=1)
condpipedepvoleid = models.BigIntegerField(blank=True, null=True, default=1)
condpipedepconssid = models.BigIntegerField(blank=True, null=True, default=1)
condpipedepconseid = models.BigIntegerField(blank=True, null=True, default=1)
txt = models.CharField(max_length=254, blank=True, null=True)
def __unicode__(self):
return self.oid
#receiver(post_save, sender=w_orders)
def ensure_order_exists(sender, **kwargs):
if kwargs.get('created', False):
tobjects.objects.get_or_create(wid=kwargs.get('instance'))
workorder_edit.html
{% extends 'workorders/base.html' %}
{% block jumbotron2 %}
<div class="jumbotron">
<h1>Navbar example</h1>
<p class="lead">This example is a quick exercise to illustrate how the top-aligned navbar works. As you scroll, this navbar remains in its original position and moves with the rest of the page.</p>
<a class="btn btn-lg btn-primary" href="../../components/navbar/" role="button">View navbar docs »</a>
</div>
{% endblock %}
{% load static %}
{% block content %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
{{ formset.management_form }}
{% for form in formset %}
{{ form.as_p }}
{% endfor %}
<input type="submit" value="Save">
</form>
workorder_create.html
{% extends 'workorders/base.html' %}
{% block jumbotron2 %}
<div class="jumbotron">
<h1>Navbar example</h1>
<p class="lead">This example is a quick exercise to illustrate how the top-aligned navbar works. As you scroll, this navbar remains in its original position and moves with the rest of the page.</p>
<a class="btn btn-lg btn-primary" href="../../components/navbar/" role="button">View navbar docs »</a>
</div>
{% endblock %}
{% load static %}
{% block content %}
<form method="POST" action="">
{% csrf_token %}
<div class="page-header">
<h2> Create Workorder </h2>
</div>
{{ form.non_field_errors }}
<div class="row">
<div class="col-md-4">
{{ form.datedefwo.errors }}
<label for="{{ form.datedefwo.id_for_label }}">Defined:</label>
{{ form.datedefwo }}
</div>
</div>
<br>
<div class="row">
<div class="col-md-4">
{{ form.typeid.errors }}
<label for="{{ form.typeid.id_for_label }}">Order type:</label>
{{ form.typeid }}
</div>
</div>
<br>
<div class="row">
<div class="col-md-4">
{{ form.datesched.errors }}
<label for="{{ form.datesched.id_for_label }}">Date Scheduled:</label>
{{ form.datesched }}
</div>
</div>
<br>
<div class="row">
<div class="col-md-4">
{{ form.statusid.errors }}
<label for="{{ form.statusid.id_for_label }}">Status:</label>
{{ form.statusid }}
</div>
</div>
<br>
<div class="row">
<div class="col-md-4">
{{ form.navreasoncomp.errors }}
<label for="{{ form.navreasoncomp.id_for_label }}">Request:</label>
{{ form.navreasoncomp }}
</div>
</div>
<div class="row">
<div class="col-md-4">
{{ form.navcustadr.errors }}
<label for="{{ form.navcustadr.id_for_label }}">Address:</label>
{{ form.navcustadr }}
</div>
</div>
<div class="row">
<div class="col-md-4">
{{ form.navname.errors }}
<label for="{{ form.navname.id_for_label }}">Customer:</label>
{{ form.navname }}
</div>
</div>
<div class="row">
<div class="col-md-4">
{{ form.navphoneno.errors }}
<label for="{{ form.navphoneno.id_for_label }}">Tel No:</label>
{{ form.navphoneno }}
</div>
</div>
<div class="row">
<div class="col-md-4">
{{ form.mapurl.errors }}
<label for="{{ form.mapurl.id_for_label }}">Map:</label>
{{ form.mapurl }}
</div>
</div>
<br>
<input type="submit" value="Save">
</form>
{% endblock %}
views.py
def workorders_list(request):
workorders_all = w_orders.objects.all().values_list('Id', flat=True)
return render(request, "workorders_list.html")
def home_page(request):
return render(request, "home_page.html")
def workorder_create(request):
if request.method == "POST":
form = CreateWorkorder(request.POST)
if form.is_valid():
CreateWorkorder_item = form.save(commit=False)
CreateWorkorder_item.save()
return redirect('/workorder/' + str(CreateWorkorder_item.Id) + '/')
else:
form = CreateWorkorder()
return render(request, 'workorders/workorder_create.html', {'form': form})
tobjectsFormSet = modelformset_factory(tobjects, fields=['wid', 'objtypegisid', 'objgisid', 'condgenid', 'condriskid', 'condratsid', 'condmhcoverid', 'condmhwallid', 'condpipehydrsid', 'condpipehydreid', 'condpipedepvolsid', 'condpipedepvoleid', 'condpipedepconssid', 'condpipedepconseid', 'txt'])
def workorder_edit(request, id=None):
item = get_object_or_404(w_orders, Id=id)
form = CreateWorkorder(request.POST or None, instance=item)
if form.is_valid():
new_order=form.save()
new_order.save()
formset = tobjectsFormSet(request.POST or None, request.FILES or None, extra=0)
if formset.is_valid():
formset.save()
return redirect('/workorder/' + str(item.Id) + '/')
else:
formset = tobjectsFormSet(request.POST or None, request.FILES or None)
return render(request, 'workorders/workorder_edit.html', {'formset': formset, 'form': form})
forms.py
class DateInput(forms.DateInput):
input_type = 'date'
class CreateWorkorder(forms.ModelForm):
navreasoncomp = forms.CharField(widget=forms.TextInput(
attrs={
'class': 'form-control',
}
))
navcustadr = forms.CharField(widget=forms.TextInput(
attrs={
'class': 'form-control',
}
))
navname = forms.CharField(widget=forms.TextInput(
attrs={
'class': 'form-control',
}
))
navphoneno = forms.CharField(widget=forms.TextInput(
attrs={
'class': 'form-control',
}
))
mapurl = forms.CharField(widget=forms.TextInput(
attrs={
'class': 'form-control',
}
))
class Meta:
model = models.w_orders
fields = ['Id', 'datedefwo', 'datesched', 'datefinished', 'statusid', 'sign', 'typeid', 'comments', 'navid', 'navkonsid', 'navdebt', 'navpropcode', 'navdepcode', 'nightshift', 'priority', 'stid', 'datesched', 'statusid', 'navreasoncomp', 'navcustadr', 'navname', 'navphoneno', 'mapurl']
widgets = {
'datedefwo': DateInput(attrs={'class':'datepicker'}),
'datesched': DateInput(attrs={'class':'datepicker'}),
'datefinished': DateInput(attrs={'class':'datepicker'}),
'navreasoncomp': forms.Textarea(attrs={'rows':3, 'cols':42}),
}
class createobject(forms.ModelForm):
wid = forms.IntegerField(widget=forms.TextInput(
attrs={
'class': 'form-control',
}
))
txt = forms.CharField(widget=forms.TextInput(
attrs={
'class': 'form-control',
}
))
class Meta:
model = models.tobjects
fields = ['wid', 'objtypegisid', 'objgisid', 'condgenid', 'condriskid', 'condratsid', 'condmhcoverid', 'condmhwallid', 'condpipehydrsid', 'condpipehydreid', 'condpipedepvolsid', 'condpipedepvoleid', 'condpipedepconssid', 'condpipedepconseid', 'txt']
urls.py
urlpatterns = [
url(r'^workorder/create/$', views.workorder_create, name='create_workorder'),
url(r'^workorder/edit/(?P<id>\d+)/$', views.workorder_edit, name='edit_workorder'),
url(r'^workorder/(?P<id>\d+)/$', views.workorder, name='workorder'),
url(r'^home/$', views.home_page, name='home_page'),
url(r'^workorders/$', views.workorders_list, name='workorders_list'),
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 having some trouble getting a file to post via a form using generic class-based view CreateView. Below is what i have so far. I am not quite sure how to handle the file and if request.FILES is getting the file being posted or if there is something else i need to be doing to capture the file information in the form. I have tried following the docs, however no luck in getting something working. File uploads as a blank field.
views.py
# Create
class FileUploadCreateView(BSModalCreateView):
template_name = 'fileupload/create-file.html'
form_class = FileUploadModelForm
success_message = 'Success: File was uploaded.'
success_url = reverse_lazy('files_list')
# Add required field my_user prior to posting form
def form_valid(self, form):
form = FileUploadModelForm(self.request.POST, self.request.FILES)
self.object = form.save(commit=False)
self.object.my_user = self.request.user
self.object.file_status = 'ready'
return super().form_valid(form)
forms.py
class FileUploadModelForm(BSModalModelForm):
class Meta:
model = FileUpload
fields = ['file_name', 'file_description', 'file_date_from', 'file_date_to','file_upload']
widgets = {
'file_name': forms.TextInput(attrs={'class':'form-control mb-3', 'id':'ruleset_name'}),
'file_description': forms.Textarea(attrs={'rows':5}),
'file_date_from': DatePickerInput(
options={
"format": "MM/DD/YYYY",
"showClose": True,
"showClear": True,
"showTodayButton": True,
}
),
'file_date_to': DatePickerInput(
options={
"format": "MM/DD/YYYY",
"showClose": True,
"showClear": True,
"showTodayButton": True,
}
),
'file_upload': forms.FileInput(attrs={'class':'form-control-file mb-3', 'id':'file_upload', 'type':'file', }),
}
html
{% load widget_tweaks %}
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal-header">
<h5 class="modal-title" style="color:#7a7a7a;">
<i class="fas fa-plus-square fa-med pr-2 align-middle"></i>
<span class="align-middle">ADD File</span>
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}" style="font-size: small; color:#7a7a7a;">{{ field.label }}</label>
{% render_field field class="form-control" %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="submit-btn btn btn-primary pr-4 pl-4">Save</button>
</div>
</form>
model.py
class FileUpload(models.Model):
"""
Class for the creation of file uploads
"""
id = models.AutoField(primary_key=True)
my_user = models.ForeignKey('users.MyUser', on_delete=models.CASCADE, related_name='file_uploads', default=None)
file_name = models.CharField(max_length=255, blank=False, default=None, verbose_name='File Name')
file_description = models.CharField(max_length=255, blank=False, default=None, verbose_name='File Description')
file_date_from = models.DateField(default=None, null=True, blank=False, verbose_name='File Date From')
file_date_to = models.DateField(default=None, null=True, blank=False, verbose_name='File Date To')
STATUS_CHOICES = (
('ready','Ready'),
('processed', 'Processed'),
('archived','Archived'),
)
file_status = models.CharField(max_length=9, choices=STATUS_CHOICES, default=None, blank=False, verbose_name='File Status')
file_create_date = models.DateTimeField(verbose_name='File Create Date', auto_now_add=True)
file_upload = models.FileField(upload_to='uploads/%Y/%m/%d/', default=None, verbose_name='File Upload', blank=True)
class Meta:
ordering = ['-file_create_date']
constraints = [
models.UniqueConstraint(fields=['my_user','file_name'], name='Unique MyUser File')
]
def __str__(self):
return self.file_name
Pretty sure you forgot to add the enctype="multipart/form-data" data attribute to the form tag in your template.
To be sure, you would have to provide us with the Model, the Form and the template code.
after working on the view for some time, I was able to get the file to post via the following, using cleaned_data.
# Add required fields prior to posting form
def form_valid(self, form):
self.instance = form.save(commit=False)
self.instance.my_user = self.request.user
self.instance.file_status = 'ready'
self.instance.file_upload = form.cleaned_data['file_upload']
return super().form_valid(form)
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()
I'm applying a validation for the datepicker when the user selects a future date. So far, the form does not save an invalid entry but the problem is that it doesn't display the error message for the field. This is what I've tried so far:
forms.py
class PostPagos(forms.ModelForm):
def clean(self):
cleaned_data = super(PostPagos, self).clean()
fecha = cleaned_data.get('fecha')
hoy = datetime.date.today()
if fecha > hoy:
raise forms.ValidationError(
'La Feha no puede ser mayor al día de hoy')
class Meta:
model = Pagos
fields = ('carro', 'pago', 'fecha', 'semana', 'renta')
widgets = {'fecha': forms.DateInput(attrs={'type': 'date'}),
'semana': forms.DateInput(attrs={'type': 'week'})
}
views.py
class PagosCreate(CreateView):
form_class = PostPagos
template_name = "AC/add_expense.html"
def form_valid(self, form):
object = form.save(commit=False)
object.startweek, object.endweek = self.weekdatetimeconverter(
object.semana)
object.save()
return super(PagosCreate, self).form_valid(form)
def weekdatetimeconverter(self, semana):
d = semana
startweek = datetime.datetime.strptime(d + '-1', "%Y-W%W-%w")
endweek = datetime.datetime.strptime(d + '-0', "%Y-W%W-%w")
return (startweek, endweek)
models.py
class Pagos(models.Model):
carro = models.ForeignKey(
Carros, on_delete=models.CASCADE, blank=False, null=False)
pago = models.DecimalField(max_digits=6, decimal_places=2)
fecha = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
semana = models.CharField(max_length=20)
startweek = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
endweek = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
renta = models.ForeignKey(
Renta, on_delete=models.PROTECT, blank=False, null=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Pagos"
def get_absolute_url(self):
return reverse('pagos')
HTML
{% extends "base.html" %}
{% load widget_tweaks %}
{% block content %}
<div class='container'>
<form method="POST">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="form-group">
<div class='column'>
<label>{{ field.label_tag }}</label>
{% render_field field class="form-control" %}
{% for error in field.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
</div>
{% endfor %}
<div class="form-group">
<button type="submit" class="btn btn-success">
<span class="glyphicon glyphicon-ok"></span> Save
</button>
Cancel
</div>
</form>
</div>
{% endblock content%}
I'm using django-widget-tweaks
After reading again the documentation [https://docs.djangoproject.com/en/3.0/ref/forms/validation/#cleaning-a-specific-field-attribute][1]
one of my mistakes was that I was not doing a return, and it turns out the code needed was way simple to what I had, here it goes:
forms.py
class PostPagos(forms.ModelForm):
def clean_fecha(self):
fecha = self.cleaned_data['fecha']
if fecha > datetime.date.today():
raise forms.ValidationError(
'La Fecha no puede ser mayor al día de hoy')
return fecha
class Meta:
model = Pagos
fields = ('carro', 'pago', 'fecha', 'semana', 'renta')
widgets = {'fecha': forms.DateInput(attrs={'type': 'date'}),
'semana': forms.DateInput(attrs={'type': 'week'})
}
Coming from Angular, this was easy to do, but I am not sure where to begin on creating a dropdown form that will filter from a list of objects. Basically, I have the code below, that will pull in and display all real estate listings; I would like to create a dropdown that will have 2 selections, 'Featured' and 'New Listing' and when a user selects one, the list will filter out and display only those listings that match. Thank you for your help.
Here is my model
from django.db import models
from django.utils import timezone
class Listing(models.Model):
FAIR = 'FAIR'
GOOD = 'GOOD'
VERY_GOOD = 'VERY_GOOD'
EXCELLENT = 'EXCELLENT'
NEW_LISTING = 'NEW_LISTING'
PRICE_REDUCED = 'PRICE_REDUCED'
UNDER_AGREEMENT = 'UNDER_AGREEMENT'
SOLD = 'SOLD'
YES = 'YES'
NO = 'NO'
FULL_SERVICE = 'FULL_SERVICE'
FOR_LEASE = 'FOR_LEASE'
WITH_REAL = 'WITH_REAL'
QUICK_SERVE = 'QUICK_SERVE'
CONDITION_CHOICES = (
('FAIR', 'Fair'),
('GOOD', 'Good'),
('VERY_GOOD', 'Very Good'),
('EXCELLENT', 'Excellent'),
)
STATUS_CHOICES = (
('NEW_LISTING', 'New Listing'),
('PRICE_REDUCED', 'Price Reduced'),
('UNDER_AGREEMENT', 'Under Agreement'),
('SOLD', 'Sold'),
)
FEATURED_CHOICES = (
('YES', 'Yes'),
('NO', 'No'),
)
LOCATION_TYPE = (
('FULL_SERVICE', 'Full Service'),
('FOR_LEASE', 'For Lease'),
('WITH_REAL', 'With Real'),
('QUICK_SERVE', 'Quick Serve'),
)
photo = models.ImageField(upload_to="media/properties/", max_length=250, blank=True, null=True)
broker = models.ForeignKey('auth.User')
phone = models.CharField(max_length=20, null=True)
title = models.CharField(max_length=250, null=True)
description = models.TextField(null=True)
concept = models.CharField(max_length=250, null=True)
location = models.CharField(max_length=250, null=True)
size = models.CharField(max_length=250, null=True)
seating = models.CharField(max_length=250, null=True)
condition_choices = models.CharField(max_length=20, choices=CONDITION_CHOICES, blank=True)
hours = models.CharField(max_length=250, null=True)
asking_price = models.CharField(max_length=250, null=True)
sales_price = models.CharField(max_length=250, null=True)
rent_price = models.CharField(max_length=250, null=True)
lease_terms = models.CharField(max_length=250, null=True)
licenses = models.CharField(max_length=250, null=True)
parking = models.CharField(max_length=250, null=True)
status_choices = models.CharField(max_length=20, choices=STATUS_CHOICES, blank=True, null=True)
featured_choices = models.CharField(max_length=5, choices=FEATURED_CHOICES, blank=True, null=True)
location_type = models.CharField(max_length=20, choices=LOCATION_TYPE, blank=True, null=True)
created_date = models.DateTimeField(default=timezone.now, null=True)
published_date = models.DateTimeField(default=timezone.now, null=True)
listing_order = models.PositiveIntegerField(default=0, blank=False, null=False)
class Meta(object):
ordering = ('listing_order',)
def publish(self):
"""This is a docstring"""
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
And here is my template
{% extends "listing/base.html" %}{% load staticfiles %}
{% block content %}
<section class="listings mt64 mb64">
<div class="container">
{% for listing in listings %}
<div class="row">
<div class="col-md-4">
<div class="listings-photo" style="background: #ccc url('{{ MEDIA_URL }}{{ listing.photo.name }}')no-repeat 50% 50%; background-size: cover; width: 350px; height: 220px"></div>
</div>
<div class="col-md-8">
<h3 class="uppercase">{{ listing.title }}</h3>
<p><span class="listings-title">Description:</span> {{ listing.description }}</p>
<div class="row">
<div class="col-md-6">
<ul>
<li><span class="listings-title">Concept:</span> {{ listing.concept }}</li>
<li><span class="listings-title">Location:</span> {{ listing.location }}</li>
<li><span class="listings-title">Size:</span> {{ listing.size }}</li>
<li><span class="listings-title">Seating:</span> {{ listing.seating }}</li>
<li><span class="listings-title">Condition:</span> {{ listing.condition_choices }}
</li>
<li><span class="listings-title">Hours:</span> {{ listing.hours }}</li>
</ul>
</div>
<div class="col-md-6">
<ul>
<li><span class="listings-title">Asking Price:</span> {{ listing.asking_price }}
</li>
<li><span class="listings-title">Sales:</span> {{ listing.sales_price }}</li>
<li><span class="listings-title">Rent:</span> {{ listing.rent_price }}</li>
<li><span class="listings-title">Lease Terms:</span> {{ listing.lease_terms }}</li>
<li><span class="listings-title">Licenses:</span> {{ listing.licenses }}</li>
<li><span class="listings-title">Parking:</span> {{ listing.parking }}</li>
</ul>
</div>
</div>
<p>For more information please contact {{ user.first_name }} {{ user.last_name }} at {{ listing.phone }}.</p>
</div>
</div>
{% endfor %}
</div>
</section>
{% endblock content %}
I can see what you mean coming from Angular. The most classical way of doing that in Django would be creating a form with all the fields you need, then passing it to the view to process the data, filter records and pass them back to the template. I'll try to provide a basic example so you can hopefully get the idea:
Index.html:
<form action="{% url 'index' %}" method="get">
<label for="featured">Format</label>
<select name="featured">
<option value="Yes" />Yes</option>
<option value="No" />No</option>
<input type="submit" name="featured" value="Filter" />
</form>
Views.py
def index(request, template_name='index.html'):
if request.GET.get('featured'):
featured_filter = request.GET.get('featured')
listings = Listing.objects.filter(featured_choices=featured_filter)
else:
listings = Listing.objects.all()
context_dict = {'listings': listings}
return render(request, template_name, context_dict)
This is pretty self-explanatory. If there's a "featured" parameter in GET, list will get filtered, otherwise it will pass all objects. Obviously we're looking at page refresh every filter request, if you expect a bit more of a one-page experience, you have to go for ajax and post requests, or something. Also, keep in mind this snippet is just a hard-coded example. Ideally, you would want to create a ModelForm class and instantiate that, then pass it to the template - a lot more readable and maintainable if you have more filter fields. If there's complex filtering involved, you would also probably want to have an additional view for filtering purposes, but this works too, it just gets messy really quick.
Thanks for Zephi, your tip helped me a lot, but for me, only worked after I changed index.html to this:
index.html
<form action="{% url 'index' %}" method="get">
<label for="featured">Format</label>
<select name="featured">
<option value="Yes" />Yes</option>
<option value="No" />No</option>
</select> <!-- ADDED THIS LINE -->
<input type="submit" value="Filter" /> <!-- DELETE name="featured" FROM ORIGINAL CODE -->
</form>
here fragments from my app's code:
index.html
<form action="{% url 'index' %}" method="get">
<label for="featured">Format</label>
<select name="featured">
{% for adoption in typeList %}
<option value="{{ adoption }}">{{ adoption }}</option>
{% endfor %}
</select>
<input type="submit" value="Filter" />
</form>
views.py
def index(request, template_name='index.html'):
if request.GET.get('featured'):
featured_filter = request.GET.get('featured')
query = Unit.listType.filter(unitType=featured_filter)
else:
query = Unit.listType.all()
typeList = query.order_by('unitType').values_list('unitType',flat=True).distinct()
_dict = {}
for x in range(len(typeList)):
_dict[typeList[x]] = typeList[x]
return render(request, 'index.html', {'query':query, 'typeList':_dict})