Django form QuerySet for ModelChoiceField - python

I've got a Form which I'm using the following field in.
contact_country = forms.ModelChoiceField(queryset=Country.objects.all())
The Country model looks like this
class Country(models.Model):
iso = models.CharField(max_length=2)
name = models.CharField(max_length=80)
printable_name = models.CharField(max_length=80)
iso3 = models.CharField(max_length=3,null=True, blank=True)
numcode = models.IntegerField(null=True, blank=True)
special = models.BooleanField(default=False)
def __unicode__(self):
return self.printable_name
class Meta:
ordering = [ 'printable_name' ]
The 'special' field indicates that the country is "special". If the country is "special" I want it to appear before the rest of the listing - as I'm sure you've seen elsewhere on the web (e.g. English speaking countries like Australia, United Kingdom and United States at the top of the select, but also again with the rest of the countries).
Is that possible with QuerySet? Or should I be looking elsewhere?

Does contact_country = forms.ModelChoiceField(queryset=Country.objects.order_by('special')) work?

This is untested, so you may give it a try, but it may not give it what you want...
in your view do this:
specials = Country.objects.filter(special=True)
all_of = Country.objects.all()
# worst thing is, this is a list, not a queryset...
new_list = list(specials)+list(all_of)
# add new object to you form...
YourForm.base_fields['contact_country'] = forms.ChoiceField(choices=[(x.id,x) for x in new_list])
Your handicap is, yo create the list using a list, not directly from queryset
This will solve your pronblem, with a dirty looking way, but it is a solution i used when modelform can not help you...

You can override the default ordering:
class Meta:
ordering = [ '-special', 'printable_name' ]
You can also write a custom manager but it doesn't worth...

Related

How to reduce quantity of an item in main table when it is being used in another table - django

I am creating my model in Django and I have a many to many relationship between supplies and van kits. The idea is that an "item" can belong to many "van kits" and a "van kit" can have many " items. I created an intermediary model that will hold the relationship, but I am struggling to figure out a way to relate the quantity in the van kit table to the quantity in the main supplies table. For example, if I wanted to mark an item in the van kit as damaged and reduce the quantity of that supply in the van kit, I would also want to reduce the total count of that supply in the main "supplies" table until it has been replenished. I am thinking that maybe I'll have to create a function in my views file to carry out that logic, but I wanted to know if it could be implemented in my model design instead to minimize chances of error. Here's my code:
class supplies(models.Model):
class Meta:
verbose_name_plural = "supplies"
# limit the user to selecting a pre-set category
choices = (
('CREW-GEAR','CREW-GEAR'),
('CONSUMABLE','CONSUMABLE'),
('BACK-COUNTRY','BACK-COUNTRY')
)
supplyName = models.CharField(max_length=30, blank=False) # if they go over the max length, we'll get a 500 error
category = models.CharField(max_length=20, choices = choices, blank=False)
quantity = models.PositiveSmallIntegerField(blank=False) # set up default
price = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) # inputting price is optional
def __str__(self):
return self.supplyName
class van_kit(models.Model):
supply_name = models.ManyToManyField(supplies, through='KitSupplies',through_fields=('vanKit','supplyName'), related_name="supplies")
van_kit_name = models.CharField(max_length=100)
vanName = models.ForeignKey(vans, on_delete=models.CASCADE)
def __str__(self):
return self.van_kit_name
class KitSupplies(models.Model):
supplyName = models.ForeignKey(supplies, on_delete=models.CASCADE)
vanKit = models.ForeignKey(van_kit, on_delete=models.CASCADE)
quantity = models.PositiveSmallIntegerField(blank=False)
def __str__(self):
return str(self.supplyName)
class Meta:
verbose_name_plural = 'Kit Supplies'
I am fairly new to django, I have to learn it for a class project so if my logic is flawed or if a better way to do it is obvious, please respectfully let me know. I'm open to new ways of doing it. Also, I've read through the documentation on using "through" and "through_fields" to work with the junction table, but I'm worried I may not be using it correctly. Thanks in advance.
One option would be to drop/remove the field quantity from your supplies model and just use a query to get the total quantity.
This would be a bit more expensive, as the query would need to be run each time you want to know the number, but on the other hand it simplifies your design as you don't need any update logic for the field supplies.quantity.
The query could look as simple as this:
>>> from django.db.models import Sum
>>> supplies_instance.kitsupplies_set.aggregate(Sum('quantity'))
{'quantity__sum': 1234}
You could even make it a property on the model for easy access:
class supplies(models.Model):
...
#property
def quantity(self):
data = self.kitsupplies_set.aggregate(Sum('quantity'))
return data['quantity__sum']

Dynamic field value in Django class

I want to create one dynamic field value for my class in Django using PyCharm.
CATEGORY_CHOICES = (
('on','one'),
('tw','two'),
('th','three'),
('fo','four'),
('fi','five'),
)
class art(models.Model):
Title=models.CharField(max_length=300)
Desciption=models.TextField()
Category=models.CharField(max_length=2, choices=CATEGORY_CHOICES)
I want the category field in my class to take more than one option, maybe two or more.
Any help would be appreciated.
If you want one python model to have multiple categories, then you need django ManyToManyField. Basically one model object could have multiple choices, one choice can also belong to multiple models objects:
class Category(models.Model):
category_name = models.CharField(max_length=10, unique=True)
class Art(models.Model):
title = models.CharField(max_length=300)
description = models.TextField()
category = models.ManyToManyField('Category', blank=True)
Note that I put unique=True for category_name to avoid creating duplicate categories.
Something not related, you shouldn't use lower fist in model name, and upper first for field name, that's really BAD naming convention and might confuse others who read your code.
Example:
# create your category in code or admin
one = Category.objects.create(category_name='one')
two = Category.objects.create(category_name='two')
three = Category.objects.create(category_name='three')
# create a new art obj
new_art = Art.objects.create(title='foo', description='bar')
# add category to Art obj
new_art.category.add(one)
new_art.category.add(two)
# category for new art obj
new_art_category = new_art.category.all()
# get only a list of category names
category_names = new_art_category.values_list('category_name', flat=True)
# create another Art obj
new_art2 = Art.objects.create(title="test", description="test")
# assign category to new_art2
new_art2.category.add(two)
new_art2.category.add(three)
Django doc for many to many and python pep8 doc.

django: set model fields as choices in models.py

Is it possible to set the choices of a field from another table?
for example
class Initial_Exam(models.Model):
Question_category = models.CharField(max_length=20, choices = Job.Job_Position)
class Job(models.Model):
Job_Position = models.CharField(max_length=30, null=True)
something like that
To close this:
As commented above, instead of twisting my implementation, setting the foreign key for Initial_Exam and using __unicode__ on Job did the job
should look like this:
class Job(models.Model):
Job_Position = models.CharField(max_length=30, null=True)
def __unicode__(self):
return self.Job_Requirements
that would display the Job_Position as choices in the admin panel
I thank the community, really appreciate it
You can definitely tie to another model with a ForeignKey relationship, but if you've got a smaller number of choices, here's a pattern you might want to consider for smaller choice lists (I use it for fairly constant choice lists less than 10):
class FrequencyType(models.Model):
FREQ_MONTHLY = 1
FREQ_QUARTERLY = 3
FREQ_YEARLY = 12
FREQ_CHOICES = (
(FREQ_MONTHLY, 'Monthly'),
(FREQ_QUARTERLY, 'Quarterly'),
(FREQ_YEARLY, 'Yearly'),
)
frequency = models.SmallIntegerField(default=FREQ_MONTHLY, choices=FREQ_CHOICES)
or, another example:
class YesNoModel(models.Model):
NO = 0
YES = 1
YESNO_CHOICES = (
(NO, 'No'),
(YES, 'Yes'),
)
weight = models.IntegerField(default=NO, choices=YESNO_CHOICES)
Good luck.

Django one-to-many relations in a template

I am searching of a method to obtain html forms from some one-to-many relations, like order-lineorder, invoice-lineinvoice, etc.
Let me an example:
# models.py
class Order(models.Model):
date = models.DateTimeField()
number = models.IntegerField(default=0)
class LineOrder(models.Model):
description = models.TextField()
price = models.FloatField()
order = models.ForeignKey(Order)
# views.py
def order_form(request):
form = OrderForm()
table_lineorder = LineOrderTable([])
RequestConfig(request).configure(table)
return render(request, "order_form.html", {"form": form, "table": table_lineorder})
Then, I want to obtain the order template with "generic attributes" (date, number), and a table list (originally empty) of lines order. Add some action like add, edit and remove must be possible.
I think that a solution like django-tables2 is possible, but I can't add rows dinamically, I think.
Thanks in advice.
[EDIT]
I have found the solution. It is django-dynamic-formset
I'm not quite clear about your question, but I guess this might be what you want:
class Order(models.Model):
date = models.DateTimeField()
number = models.IntegerField(default=0)
items = model.ManyToManyField(Item)
class Item(models.Model):
description = models.TextField()
price = models.FloatField()
It should be equivalent to one-to-many if you don't assign one Item to multiple Orders.

use Manytomanyfield inputs in a model to create get_absolute_url

I have to create get_absolute_url from an input given into a manytomanyfield.
Here is the relevant model.
class ConnectTag(models.Models):
whitetags = models.ManyToManyField(Tag, related_name='whitectags')
name = models.CharField(max_length=20, blank=True)
user = models.ForeignField(User, related_name='directconnecttags')
detail = models.TextField(blank=True)
def get_absolute_url:
return "%s.%s.%s...." %tag1,%tag2 ,%tagn
where tag1,tag2,tag3 are whitetags. How do I rewrite the last line into actual code ?
Not entirely clear what you're asking, but this might help:
return '.'.join(self.whitetags.values_list('fieldname', flat=True))
where fieldname is the field name on the Tag model which you want to output.

Categories

Resources