Add choices in ListView Django - django

I have the view which displays all transactions. I have a table with contractors and I want to display all rows from this table in the options to <select>. How can i do this?
My view:
class TransactionView(CustomPermissionRequired, ListView):
# Переопределение из MultipleObjectMixin
model = Transaction
context_object_name = 'transactions'
paginate_by = 20
login_url = '/'
permission_required = (
'registration2.can_see_payments',
)
# Переопределение из TemplateResponseMixin
template_name = 'payments.html'
search_fields = [
('contractor_name', 'deal__service__contractor__name__icontains'),
('from_pay_date', 'payment_date__gte'),
('to_pay_date', 'payment_date__lte'),
('tr_id', 'id__icontains')
]
# Переопределение из MultipleObjectMixin
def get_queryset(self):
print('get_def')
filter_args = []
filter_kwargs = {}
for sf in self.search_fields:
if sf[0] is not None:
sf_value = self.request.GET.get(sf[0])
if sf_value:
filter_kwargs[sf[1]] = sf_value
return Transaction.objects.all().select_related('currency',
'payment_source__payment_type',
'deal__service__contractor'
).filter(*filter_args, **filter_kwargs).order_by('-id')
def get_context_data(self, **kwargs):
context = super(TransactionView, self).get_context_data(**kwargs)
for sf in self.search_fields:
if sf[0] is not None:
context[sf[0]] = self.request.GET.get(sf[0])
return context
My models Transaction and Contractors:
class Transaction(models.Model):
id = models.BigIntegerField(blank=True, null=False, primary_key=True)
currency = models.ForeignKey(Currency, null=True, on_delete=models.CASCADE)
deal = models.ForeignKey(Deal, null=True, on_delete=models.CASCADE)
# service_instance = models.ForeignKey(ServiceInstance, null=True, on_delete=models.CASCADE)
payment_source = models.ForeignKey(PayerPaymentSource, null=True, on_delete=models.CASCADE)
payment_date = models.DateTimeField(blank=True, null=True)
amount = models.IntegerField(blank=True, null=True)
status = models.CharField(max_length=255, blank=True, null=True)
context = models.TextField(blank=True, null=True)
class Contractors(models.Model):
id = models.IntegerField(blank=True, null=False, primary_key=True)
name = models.CharField(max_length=255, blank=True, null=True)

You don't show your HTML, but you start from a queryset to get the contractor names and ids.
contractors = Contractors.objects.all().order_by('name').values_list('id, 'name')
If you look at list(contractors) you will see it is a list of 2-tuples as required for choices.
You can use it as such if you dynamically build a form, or you can pass it to your template and iterate through it there to build an options list
{% for c in contractors %} <option ... {{c.0}} ... {{c.1}} ... {% endfor %}
There's also forms.ModelChoiceField which IIRC accepts a queryset (without values_list()) as an argument, and returns the selected [Contractor] instance as its entry in form.cleaned_data.

Related

django how to get user to display specific object

I'm learning django and I'm trying to display all items from a specific user which is the 2003-111
itemid sy sem resolve_by
book 2021-2022 2 2003-111
table 2021-2022 1 2012-455
here's my models.py I'm using customuser to use email as authentication instead of username and replace my id with userid(character)
class ClearanceCustomuser(models.Model):
password = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)
is_superuser = models.BooleanField()
userid = models.CharField(primary_key=True, max_length=9)
email = models.CharField(unique=True, max_length=254)
is_staff = models.BooleanField()
is_active = models.BooleanField()
date_joined = models.DateTimeField()
class Meta:
managed = False
db_table = 'clearance_customuser'
class ClearanceItem(models.Model):
itemid = models.CharField(primary_key=True, max_length=20)
sem = models.CharField(max_length=1, blank=True, null=True)
sy = models.CharField(max_length=9, blank=True, null=True)
resolve_by = models.ForeignKey('ClearanceCustomuser', models.DO_NOTHING,
db_column='resolve_by', blank=True, null=True)
class Meta:
managed = False
db_table = 'clearance_item'
for now this is my views.py
def index(request):
context = {}
context['items'] = ClearanceItem.objects.all()
return render(request, 'clearance/index.html', context)
which is displaying all items. I was thinking of something like this
select b.cl_itemid,b.sem,b.sy,b.resolve_by
from curriculum.clearance_customuser a
INNER JOIN curriculum.clearance_item b ON a.userid = b.resolve_by
where resolve_by = '2003-221'
if 2003-111 is userid field of ClearanceCustomuser than you go like:
def index(request):
context = {}
context['items'] = ClearanceItem.objects.filter(resolve_by__userid='2003-111')
return render(request, 'clearance/index.html', context)
if you want to pass userid as parameter in yours urls.py edit path to index:
path('<str:userid>/', views.index, name='index')
and in view:
def index(request, userid):
context = {}
context['items'] = ClearanceItem.objects.filter(resolve_by__userid=userid)
return render(request, 'clearance/index.html', context)

unable to fetch item from selected categories in django

i want to fetch the item of related subcategories but i am unable to fetch the items from that subcategories it is showing me the error
AttributeError: 'Subcategories' object has no attribute 'item'
so here is my code
my models
class Subcategories(models.Model):
categories = models.ForeignKey(Categories, on_delete=models.CASCADE, related_name='our_categories')
name = models.CharField(max_length=200, blank=False)
joined_date = models.DateTimeField(default=timezone.now,editable=False)
update_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Item(models.Model):
categories = models.ForeignKey(Categories, on_delete=models.CASCADE,)
subcategories = models.ForeignKey(Subcategories, on_delete=models.CASCADE, related_name='products')
can_buy = models.ForeignKey(For, on_delete=models.CASCADE,)
name = models.CharField(max_length=200, blank=False)
contain_size = models.CharField(max_length=10, blank=True)
first = models.ImageField(upload_to='items', blank=False)
second = models.ImageField(upload_to='items', blank=True)
third = models.ImageField(upload_to='items', blank=True)
fourth = models.ImageField(upload_to='items', blank=True)
fifth = models.ImageField(upload_to='items', blank=True)
item_vedio = models.FileField(upload_to='item_vedio', blank=True)
offered_price = models.FloatField(blank=False,)
actual_price = models.FloatField(blank=False)
about = models.TextField(blank=False, default="about" )
offer = models.CharField(max_length=4, blank=True)
def __str__(self):
return self.name
my urls.py
urlpatterns = [
path('<int:subcategory_id>/products/',Product.as_view(),name='product' ),
]
my views.py
class Product(View):
def get(self, request,):
category_list = Categories.objects.all()
return render (request, 'products.html', {'category_list': category_list })
def get(self, request, subcategory_id):
subcategory = get_object_or_404(Subcategories, pk=subcategory_id)
products = subcategory.item.all()
return render (request, 'products.html',{"subcategory_list" : products })
any idea what causing the issue and thank you for your time
The related name is products for subcategories Foreign key in Item model.
subcategory.products.all()

Django how to generate a filtered queryset

I have got 2 models. Asset and Asset_Type. In my asset_type detail view i would like to list all assets of that asset type. I think I have to use models.Asset.queryset().filter() but i can't get it to work.
On my template I would like to loop though the list with a 'for' (example: object in list) and print the values like this {{ object.name }}
models.py
class Asset(models.Model):
# Relationships
room = models.ForeignKey("asset_app.Room", on_delete=models.SET_NULL, blank=True, null=True)
model_hardware = models.ForeignKey("asset_app.Model_hardware", on_delete=models.SET_NULL, blank=True, null=True)
# Fields
name = models.CharField(max_length=30)
serial = models.CharField(max_length=30, unique=True, blank=True, null=True, default=None)
mac_address = models.CharField(max_length=30, null=True, blank=True)
purchased_date = models.DateField(null=True, blank=True)
may_be_loaned = models.BooleanField(default=False, blank=True, null=True)
notes = models.TextField(max_length=448, null=True, blank=True)
ip = models.CharField(max_length=90, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name)
def get_absolute_url(self):
return reverse("asset_app_asset_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_asset_update", args=(self.pk,))
class Asset_type(models.Model):
# Fields
name = models.CharField(max_length=30)
last_updated = models.DateTimeField(auto_now=True, editable=False)
created = models.DateTimeField(auto_now_add=True, editable=False)
notes = models.TextField(max_length=448, null=True, blank=True)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name)
def get_absolute_url(self):
return reverse("asset_app_asset_type_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_asset_type_update", args=(self.pk,))
class Model_hardware(models.Model):
# Relationships
asset_type = models.ForeignKey("asset_app.Asset_type", on_delete=models.SET_NULL, blank=True, null=True)
brand = models.ForeignKey("asset_app.Brand", on_delete=models.SET_NULL, blank=True, null=True)
# Fields
name = models.CharField(max_length=30)
notes = models.TextField(max_length=448, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name) + " :: " + str(self.brand.name) + " :: " + self.asset_type.name
def get_absolute_url(self):
return reverse("asset_app_model_hardware_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_model_hardware_update", args=(self.pk,))
views.py
class Asset_typeDetailView(generic.DetailView):
model = models.Asset_type
form_class = forms.Asset_typeForm
You can simply iterate over the related objects in the template by using the default related name which is the model name in lowercase with _set appended. So asset_type.model_hardware_set.all() will give you all Model_hardware instances related to Asset_type and similarly for model_hardware.asset_set.all():
{% for model_hardware object.model_hardware_set.all %}
{% for asset in model_hardware.asset_set.all %}
{{ asset.name }}
{% endfor %}
{% endfor %}
But this can become slow, since we run into the N + 1 problem that is for each model hardware we will be making queries to get it's assets. We can use prefetch_related_objects on your model instance to prefetch all the related objects (in fewer queries) this and make it faster:
from django.db.models import prefetch_related_objects
from django.views.generic import DetailView
class YourDetailView(DetailView):
model = Asset_type
template_name = '<your_template_name>.html'
def get_object(self, queryset=None):
obj = super().get_object(queryset=queryset)
prefetch_related_objects([obj], 'model_hardware__asset')
return obj
Note: Class names in python should ideally be in PascalCase not Some_case (Don't think there is any such convention as you make
here), hence ModelHardware instead of Model_hardware and
AssetType instead of Asset_type would be better names.

Django DetailView filter by two parameters not using the primary key

I need to filter a model by two values that none of them is the PK of the model.
I want to filter the payments for an specific car and week, this means that I can have more than one payment for a car and in a week.
I'm using Django-Tables2 to display the results.
views.py
class PagosDetailView(SingleTableMixin, DetailView):
template_name = "AC/paymentsbycarandweek.html"
context_table_name = 'table'
model = Pagos
table_class = PagosTable
slug_url_kwarg = 'carro_id'
def get_queryset(self):
qs = super(PagosDetailView, self).get_queryset()
return qs.filter(carro=self.kwargs['carro'], semana=self.kwargs['semana'])
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')
def __str__(self):
return self.semana
urls.py
path('paymentsbycarandweek/<int:carro>/<slug:semana>',
views.PagosDetailView.as_view(), name='pagos_bycar')
This last time that I have tried several options, I'm getting the following error message:
Generic detail view PagosDetailView must be called with either an object pk or a slug in the URLconf.
How exactly can I pass these two parameters?
After searching a lot, this is how I finally resolved it:
class PagosDetailView(SingleTableMixin, ListView):
model = Pagos
table_class = PagosDetailTable
template_name = 'AC/paymentsbycarandweek.html'
paginate_by = 10
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
self.object_list = self.object_list.filter(
carro=kwargs['carro'], semana=kwargs['semana'])
context = self.get_context_data()
return self.render_to_response(context)

Django show extra content in class based view with ForeignKey models

I'm trying to add extra content to Djangos Class-based view to the template
I have some models like this
class District(models.Model):
district = models.CharField(max_length=255, null=False, unique=False, blank=True)
def __str__(self):
return self.district
class Street(models.Model):
street_name = models.CharField(max_length=255, null=False, unique=False, blank=True)
district = models.ForeignKey(District, verbose_name=_('district'), on_delete=models.CASCADE, null=True, blank=True)
zone = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.street_name
class Article(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name="author", on_delete=models.SET_NULL)
timestamp = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=1, choices=STATUS, default=CREATED)
comment = models.CharField(max_length=255, null=True, unique=False, blank=True)
name = models.CharField(max_length=255, null=True, unique=False)
street = models.ForeignKey(Street, verbose_name=_('street'), on_delete=models.CASCADE, null=True, blank=True)
class ArticlesListView(LoginRequiredMixin, PermissionRequiredMixin,ListView):
model = Article
paginate_by = 50
context_object_name = "articles"
permission_required = 'is_staff'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['Filter_name'] = Article.objects.order_by().values('name').distinct()
context['Filter_user'] = Article.objects.order_by().values('user').distinct()
return context
def get_queryset(self, **kwargs):
return Article.objects.all()
And late in the template
{% for f in Filter_name %}
<ul>
<li>{{f.name}}</li>
</ul>
{% endfor %}
How can I display a list of the district names and a list of the author names in the template with ForeignKey?
U can try something like that
{% for item in model_1.foreign_model_set.all %}
<h1>{{ item }}</h1>
{% endfor %}