django-select2: Select Field doesn't open when tabbed - django

In my simple Django App, I've implemented django-select2. I have a form with 2 fields: product and category. When I create a new product I first give it a title and than tab to the category-field, but the dropdown does not open automatically. Only when I press Space-Bar or Enter the dropdown opens.
What can I do so that the dropdown opens automatically, when it is reached?
Here my code:
forms.py
from django import forms
from django_select2.forms import Select2Widget, ModelSelect2Widget, Select2MultipleWidget
from .models import Product, Category
class MyForm(forms.ModelForm):
category = ModelSelect2Widget(queryset=Category.objects.all())
class Meta:
model = Product
fields = ['name', 'category']
widgets = {
'category': Select2Widget,
}
models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=120)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
def __str__(self):
return self.name
product.html
{% extends 'base.html' %}
{% block content %}
{{ form.media.css }}
<br>
<form action="" method="POST">
{% csrf_token %}
{{ form}}
<button type="submit">Save</button>
</form>
{{ form.media.js }}
{% endblock content %}

Related

Making a CreateForm with choices based on database values

I am making a django project and I have a form for the User to add a Vehicle Manually that will be assigned to him. I also would like to had an option for the user to choose a vehicle based on the entries already present in the database.
vehicles/models.py
class Vehicle(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
nickname = models.CharField(unique = True, max_length=150)
date_joined = models.DateTimeField(default=timezone.now)
brand = models.CharField(max_length=150)
battery = models.CharField(max_length=150)
model = models.CharField(max_length=150)
def __str__(self):
return self.nickname
def get_absolute_url(self):
return reverse('vehicle-list')
class Meta:
db_table = "vehicles"
I created a form so the user can add his Vehicles as such:
vehicles/forms.py
class VehicleAddFormManual(forms.ModelForm):
class Meta:
model = Vehicle
fields = ('brand','model', 'battery', 'nickname')
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
self.fields['brand']
self.fields['model']
self.fields['battery']
self.fields['nickname']
The corresponding view:
vehicles/views.py
class AddVehicleViewManual(LoginRequiredMixin, CreateView):
model = Vehicle
form_class = VehicleAddFormManual
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
The html file:
vehicles/templates/vehicles/vehicle_form.html
{% extends "blog/base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New Vehicle</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Submit</button>
</div>
</form>
</div>
{% endblock content %}
I would like to add another form in which the user has a dropdown with option with the brands, models and batteries that already exist in the database. If there's a car in the database with brand: Tesla, model: Model 3, battery: 50 kWh, then it would appear in the dropbox as a choice for each field.
I'm not sure how to do this and sorry for the newbie question... Thanks in advance!
I once had to do something similar, but I needed a form which had one checkbox for each item in a list of externally-supplied strings. I don't know if this is the cleanest way, but I used python metaclasses:
class SockSelectForm(forms.Form):
#staticmethod
def build(sock_names):
fields = {'sock_%s' % urllib.parse.quote(name):
forms.BooleanField(label=name, required=False)
for name in sock_names}
sub_class = type('DynamicSockSelectForm', (SockSelectForm,), fields)
return sub_class()
In my get() method, I instantiate it as:
form = SockSelectForm.build(names)
and the corresponding form handling in the post() method is:
form = SockSelectForm(request.POST)
I suspect if you look under the covers of Django's ModelForm, you'd see something similar, but I couldn't use ModelForm because it's too closely tied to the model system for what I needed to do.
model.py
class DropdownModel(models.Model):
brand = models.CharField(max_length=150)
battery = models.CharField(max_length=150)
model = models.CharField(max_length=150)
def __str__(self):
return self.brand.
form.py
from .models import DropdownModel
all_brand = DropdownModel.objects.values_list('brand','brand')
all_battery = DropdownModel.objects.values_list('battery','battery')
all_model= DropdownModel.objects.values_list('model','model')
class DropdownForm(forms.ModelForm):
class Meta:
model = DropdownModel
fields = "__all__"
widgets = {
'brand':forms.Select(choices=all_brand),
'battery':forms.Select(choices=all_battery),
'model':forms.Select(choices=all_model),
}
view.py
from django.shortcuts import render
from .form import DropdownForm
# Create your views here.
def HomeView(request):
form = DropdownForm()
context = {'form':form}
return render(request,'index.html',context)
index.html
{% extends "base.html" %}
{% load static %}
{% block title %}
Index | Page
{% endblock title %}
{% block body %}
{{form.as_p}}
{% endblock body %}
Output-
Note- if u can't see updated values in dropdown do server restart because localhost not suport auto update value fill in dropdown it's supoorted on live server
Thank you

Django Model field from foreign key which is displayed with the select tag has empty fields

Hello I have a model in Django where I have a forein key and I am displaying it with a select tag in html. However there are blank options in the selector tag but not in my database. How can I remove them. I want also to ask how I can delete the ------ option.
html, only the select tag
<select style='width:200px';name="bolum" required="" id="id_bolum">
{% for x in form.bolum %}
{% if {{x}} ''%}
{%else%}
<option value="{{x.id}}">{{x}}</option>
{% endif %}
{% endfor %}
</select>
models.py
from django.db import models
# Create your models here.
class Department(models.Model):
department=models.CharField(max_length=128)
def __str__(self):
return self.department
class WPGroup(models.Model):
bolum = models.ForeignKey('Department', on_delete=models.CASCADE, related_name='department_for_wpgroup',null=False, blank=False)
name=models.CharField(max_length=128,blank=False)
number=models.PositiveIntegerField(blank=False)
mail=models.EmailField(max_length=128,blank=False)
def __str__(self):
return self.name
forms.py
from django import forms
from .models import WPGroup
class WPGroupForm(forms.ModelForm):
class Meta:
model=WPGroup
fields=['name','number','bolum','mail']
def clean_mail(self):
email = self.cleaned_data['mail']
if "#itu.edu.tr" not in email:
raise forms.ValidationError("You must include #itu.edu.tr")
return email
here is also a screenshot of the website

How to estabalish ManyToMany relationship on instantiation of object through generic CreateView?

So I have two models. Deck and Card. When the user creates card it should be tied to a deck, in a ManyToMany relationship.
The card is created through the Generic Django create view, and I can't crack how I can assign the card to a deck, in this context. Any ideas on how I might solve this?
My CreateView
class CardCreateView(LoginRequiredMixin, CreateView):
model = Card
fields = ['question', 'answer']
def form_valid(self, form):
form.instance.creator = self.request.user
return super().form_valid(form)
def get_success_url(self):
return reverse('spaced_repitition-home')
def assign_card(self, deck_id): #It's here I don't get why it doesn't work
card = self.get_object()
deck = get_object_or_404(Deck, pk=deck_id)
card.decks.add(deck)
card.save()
Template that sends user to form (passes on deck_id)
{% for deck in decks reversed %}
<a href="{% url 'card-create' deck_id=deck.id %}">
<p> Add Card </>
{% endfor %}
Form Template
{% extends "spaced_repitition/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class=form-group>
<legend class="borders-bottom mb-4"> Create Card </legend>
{{ form|crispy }}
<div class=form-group>
<button class= "btn btn-outline-info" type="submit"> Create </button>
</div>
</fieldset>
</form>
{% endblock content %}
Models
class Deck(models.Model):
title = models.CharField(max_length=100)
date = models.DateTimeField(default=timezone.now)
creator = models.ForeignKey(User, on_delete=models.CASCADE)
description = models.TextField(max_length=200, blank=True)
def __str__(self):
return self.title
class Card(models.Model):
question = models.CharField(max_length=100)
answer = models.TextField()
date = models.DateTimeField(default=timezone.now)
creator = models.ForeignKey(User, on_delete=models.CASCADE)
decks = models.ManyToManyField(Deck)
days_till_study = models.IntegerField(default=1)
def __str__(self):
return self.question + ' pk: ' + str(self.pk)
Url
path('card/new/<int:deck_id>/', CardCreateView.as_view(), name='card-create'),
Thanks for reading this.
Edit
Found the solution here:
Django Createview default value for a foreign key field

Django forms how to display related data in an inner form

I am struggling with Django forms.
I have the following model.py:
class Property(models.Model):
portfolio = models.ForeignKey("portfolios.Portfolio", on_delete=models.CASCADE)
class PropertyImage(models.Model):
property = models.ForeignKey("Property", on_delete=models.CASCADE)
image = models.ImageField(upload_to = property_image_upload_to)
def __str__(self):
return self.image.url
class PropertyDocument(models.Model):
property = models.ForeignKey("Property", on_delete=models.CASCADE)
document = models.FileField()
class Address(models.Model):
property = models.OneToOneField("Property", on_delete=models.CASCADE)
line1 = models.CharField(max_length=100)
line2 = models.CharField(max_length=100, null=True, blank=True)
line3 = models.CharField(max_length=100, null=True, blank=True)
post_code = models.CharField(max_length=7)
town = models.CharField(max_length=100, null=True, blank=True)
city = models.CharField(max_length=100)
When adding/updating a property, I want the form to show the form for related objects like the address, documents/images instead of the select list's that appear in forms - I want to be able to add/edit the related data.
My view.py file
class PropertyCreate(CreateView):
model = Property
form_class=PropertyAddressFormSet
success_url = reverse_lazy('Property_list')
def get_context_data(self, **kwargs):
data = super(PropertyCreate, self).get_context_data(**kwargs)
return data
Property_form.html
{% extends 'base/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" class="btn btn-primary" />
<button class="btn btn-link" onclick="javascript:history.back();">Cancel</button>
</form>
{% endblock %}
urls.py
from . import views
app_name = 'properties'
urlpatterns = [
path('<int:portfolio_id>/<int:pk>/edit', views.PropertyUpdate.as_view(), name='property_edit'),
path('<int:portfolio_id>/create', views.PropertyCreate.as_view(), name='property_new'),
]
I've read about inlineformset_factories and inlineformset's etc, but is this the best choice for my scenario? If so, I can't figure out how to show the portfolio, address form
I;m currently using a inlineformset like so, which creates the Address form on the PropertyCreate view, but I want to also add in the PropertyImages and PropertyDocs to the ProertyCreate view.:
PropertyAddressFormSet = inlineformset_factory(
parent_model=Property,
model=Address,
form=AddressForm,
extra=0,
min_num=1
)
For anyone in the same boat as me, I managed to get this working with the following code:
Forms.py:
class PropertyForm(ModelForm):
""" Edit a property """
class Meta:
model = Property
exclude = ()
PropertyAddressFormSet = inlineformset_factory(
parent_model=Property,
model=Address,
form=AddressForm,
extra=0,
min_num=1
)
Views.py
class PropertyCreate(CreateView):
model = Property
form_class=PropertyForm
success_url = reverse_lazy('Property_list')
def get_context_data(self, **kwargs):
data = super(PropertyCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['address'] = PropertyAddressFormSet (self.request.POST, instance=self.object)
else:
data['address'] = PropertyAddressFormSet ()
return data
template:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form |crispy }}
<fieldset class="border p-2">
<legend class="w-auto">Address</legend>
{{ address.management_form }}
{% for form in address.forms %}
<div >
{{ form.as_p }}
</div>
{% endfor %}
</fieldset>
</form>
Hope this helps someone.

Django admin filters in custom template

I want to implement django admin filters in my custom template can any body from you help me in resolving this issue i will appreciate. i am getting this error ...... name 'AddFilter' is not defined...
models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField()
description = models.TextField()
release_date = models.DateField()
filters.py
import django_filters
class ProductFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='iexact')
class Meta:
model = Product
fields = ['price', 'release_date']
views.py
def filt_page(request):
filter = AddFilter(request.GET, queryset=Add.objects.all())
print (filter)
return render_to_response('filt_page.html',{'filter':filter})
template
<form action="" method="get"> {% csrf_token %}
{{ filter.form.as_p }}
<input type="submit" />
</form>
{% for obj in filter %}
{{ obj.name }}<br />
{% endfor %}
You've called an undefined class in your views.py
class name in filters.py is 'ProductFilter' but you've called 'AddFilter' in views.py
Also the model name in your filter is undefined, you've used 'Add' instead of 'Product'
Try
filter = ProductFilter(request.GET, queryset=Product.objects.all())