search_field by field choice - python

I've a basic django model and i was wondering is there a way to make the search fields search in the value i am mapping to instead of searching in the value saved in the database, is there a possible way that i can search by the value "Premium" ?
Model.py
class User(models.Model):
account = models.ForeignKey('Account')
name =models.CharField(max_length=50)
ACCOUNT_CHOICES = (
(1, 'Premium'),
(0, 'Normal'),)
type = models.CharField(choices=ACCOUNT_CHOICES)
Admin.py
class UserAdmin(admin.ModelAdmin):
search_fields = ['name','type']
pass
admin.site.register(User,UserAdmin)

Summary from comments discussion;
You'll need to set up a custom queryset for the search filter which attempts to reverse lookup the choice display field to its value. Another slight issue is that multiple values can have the same choice display name, so you'll need to take that into consideration.
Here is an example of how to achieve this:
https://github.com/sivaa/django-custom-search-filter/blob/master/app/admin.py

Model:
class order(models.Model):
STATUS = (
("Completed", "Completed"),
("Ordered", "Ordered"),
("Accepted", "Accepted"),
("Order Cancel", "Order Cancel"),
("Customer Cancel", "Customer Cancel"),
("Delivered", "Delivered"),
("Added to Cart", "Added to Cart"),
("Out of Delivery", "Out of Delivery"),
("Refund Initiated","Refund Initiated"),
("Return And exchange","Return And exchange"),
)
status = models.CharField(default="Ordered", max_length=50, null=True, choices=STATUS, blank=True)
View:
status1=request.POST.get("status")
response1=order.objects.filter(status__contains=status1)

Related

Django Many to Many field dependent on another many to many field

I'm creating two many-to-many fields based on same model in a single model. I would like to show only those instances in second many-to-many field which are selected in first many to many field to further apply selection. Through which approach should i handle this behaviour.
class Params(models.Model):
name = models.CharField(max_length = 200)
comments = Model.TextField()
def __str__(self):
return self.name
class Selection(models.Model):
select_params = models.ManyToManyField(Params, blank=True, related_name = "selection_1")
edit_selected_params = models.ManyToManyField(Params, blank=True, related_name =
"selection_from_selec_params")
Thanks and regards
You can use SubQuery is think:
selected = Selection.objects.filter(
edit_selected_params__in=SubQuery(
Selection.objects.filter(select_params__isnull=False).values_list("select_params", flat=True)
)
)
You can see SubQuery docs

Django - How to render a ModelForm with a Select field, specifying a disabled option?

I have the following models:
# Get or create a 'Not selected' category
def get_placeholder_categoy():
category, _ = ListingCategories.objects.get_or_create(category='Not selected')
return category
# Get default's category ID
def get_placeholder_category_id():
return get_placeholder_categoy().id
class ListingCategories(models.Model):
category = models.CharField(max_length=128, unique=True)
def __str__(self):
return f'{self.category}'
class Listing(models.Model):
title = models.CharField(max_length=256)
seller = models.ForeignKey(User, on_delete=models.CASCADE, related_name='listings')
description = models.TextField(max_length=5120, blank=True)
img_url = models.URLField(default='https://media.istockphoto.com/vectors/no-image-available-picture-coming-soon-missing-photo-image-vector-id1379257950?b=1&k=20&m=1379257950&s=170667a&w=0&h=RyBlzT5Jt2U87CNkopCku3Use3c_3bsKS3yj6InGx1I=')
category = models.ForeignKey(ListingCategories, on_delete=models.CASCADE, default=get_placeholder_category_id, related_name='listings')
creation_date = models.DateTimeField()
base_price = models.DecimalField(max_digits=10, decimal_places=2, validators=[
MinValueValidator(0.01),
MaxValueValidator(99999999.99)
])
With these, I have the following form:
class ListingForm(ModelForm):
class Meta:
model = Listing
exclude = ['seller', 'creation_date']
widgets = {
'title': TextInput(attrs=base_html_classes),
'description': Textarea(attrs=base_html_classes),
'img_url': URLInput(attrs=base_html_classes),
'category': Select(attrs=base_html_classes),
'base_price': NumberInput(attrs=base_html_classes)
}
One of the available categories I have is "Not selected", since I want to allow that if at some point a category were to be removed, items can be reassigned to that one, however, when rendering the form, I will do some validation on the view function to prevent it from being submitted if the "not selected" category is sent with the form.
Because of this, I want the HTML form on the template to assign the 'disabled' attribute to the option corresponding to that category, however, I have been searching for a couple of days now without finding anything that I was able to understand to the point where I could try it.
Ideally, another thing I'd like to achieve is to be able to modify the order of the rendered options on the form so that I can move to the top 'not selected' regardless of its primary key within the model.
I am aware I can just create a form instead of a model form, or just modify the template so I manually specify how to render the form itself, but I do feel like there is a simple fix to this either on the model or on the model form that I am just not finding yet.
Thanks in advance!
I would suggest you use (in model definition)
class Listing(models.Model):
..
category = model.ForeignKey(ListingCategories, on_delete=models.SET_NULL, null=True, related_name='listings')
..
and optionally in form definition
class ListingForm(ModelForm):
category = forms.ModelChoiceField(ListingCategories, empty_label='Not Selected')
..
While rendering model form, a required attribute will be automatically added, and in form validating, it is also required. It is only in database validation that the field can be left NULL

How can I add ordering for ManyToMany field?

I have two models: CustomUser and AgreementReglament
At this moment relation between the models looks like this:
class AgreementReglament(models.Model):
name = models.CharField(max_length=32) # just name of the reglament
approvers = models.ManyToManyField( # set of users to approve
'CustomUser',
related_name='agreement_reglaments'
)
How can I set order of approvers (e.g. CustomUser1 should be the first in particular AgreementReglament1, CustomUser2 should be second and so on, but in AgreementReglament2 CustomUser2 can be the first)
UPDATE: ordering is based on the POST request data
Example of post request to create AgreementReglament:
{
"name": "Reglament1",
"approvers": [
{
"approver_name": "Alex",
"approver_order": 1,
},
{
"approver_name": "Bob",
"approver_order": 2,
}
]
}
UPDATE2
class AgreementReglament(models.Model):
name = models.CharField(max_length=32) # name of the reglament
approvers = models.ManyToManyField( # set of users to approve
'CustomUser',
related_name='agreement_reglaments',
through='Approval'
)
class Approval(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
agreement = models.ForeignKey(
AgreementReglament,
on_delete=models.SET_NULL,
blank=True,
null=True
)
order = models.IntegerField()
If you mean the approver order value will be entered as a field , then I would create a model lets say For example Approvals and it will have a FK field for User and a FK field for Agreement , and a third field for the approver_order. And leave the Agreement Model to have only name field.
But , If you mean to sort based on a condition , the question needs more details to be clarified as (what the ordering is based on ? What is the field you’re ordering exactly ?)
UPDATE:
After seeing your update what I understood is that you get this ordering from the POST request data and for the example you provided, you definitely need a field to store the order for each User.
I suggest going with the same answer, create a model in the middle and link both models with that Model using the through attribute and that might look like this:
class Approval(models.Modal):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
agreement = models.ForeignKey(AgreementReglament, ...)
order = models.#whatever you want this char or int
and in one of the other models (doesn't really matter) they should be like this:
class AgreementReglament(models.Model):
name = models.CharField(max_length=32) # just name of the reglament
approvers = models.ManyToManyField( # set of users to approve
'CustomUser',
related_name='agreement_reglaments', through='Approval'
)
If you have any questions, feel free to ask.

Django form: Update model values based on user input in one field

I am writing a form to let a user enter a purchase from the template. A couple things need to happen:
the purchase goes to populate a row in the replenishment table
some fields of the replenishment table get updated based on what the user has input
here is what my model look like:
class replenishment(models.Model):
Id = models.CharField(max_length=100, primary_key=True, verbose_name= 'references')
Name = models.CharField(max_length=200)
Quantity = models.FloatField(default=0)
NetAmount = models.FloatField(default=0)
SupplierID = models.CharField(max_length=200)
Supplier = models.CharField(max_length=200)
SellPrice = models.FloatField(default=0)
StockOnOrder = models.FloatField(default=0)
StockOnHand = models.FloatField(default=0)
def __str__(self):
return self.reference
and the form:
class ProcurementOperationRecord(forms.Form)
Id = forms.CharField(required=True)
Quantity = forms.FloatField(required=True)
NetAmount = forms.FloatField(required=True)
Supplier = forms.CharField(required=True)
SellPrice = forms.FloatField(required=True)
I have no clue how to let the user input the values in form and automatically add Quantity to StockOnOrder as well as automatically recognize the SupplierID based on Supplier. At this point I don't know where to start really. At least, is it possible to achieve what I try to do?
First, I've changed some things around and added some comments to what and why I did them.
# models/classes in python are singular AND camel cased (99.9%)
class Supplier(models.Model):
...
# models/classes in python are singular AND camel cased (99.9%)
class Replenishment(models.Model):
# attributes are normally lower case and snake cased (99.9%)
# try not to do this, a CharField??, unless you're using a guid? if so use UUIDField()
# https://docs.djangoproject.com/en/3.1/ref/models/fields/#uuidfield
id = models.CharField(db_column='Id', max_length=100, primary_key=True, verbose_name='references')
name = models.CharField(db_column='Name', max_length=200)
quantity = models.FloatField(db_column='Quantity', default=0)
net_amount = models.FloatField(db_column='NetAmount', default=0)
# deleted your field "Supplier" -- with this change you can join to the other table and get what you need without having to duplicate anything
supplier = models.ForeignKey(Supplier, db_column='SupplierID')
sell_price = models.DecimalField(db_column='SellPrice', default=0, max_digits=6, decimal_places=2) # You're asking for trouble if you keep this as FloatField
stock_on_order = models.IntegerField(db_column='StockOnOrder', default=0) # how can you have ordered a .5 for your stock? changed to IntegerField
stock_on_hand = models.IntegerField(db_column='StockOnHand', default=0) # how can you have a .5 of your stock? changed to IntegerField
class Meta:
db_table = 'replenishment' # try not to do this either.. let django come up with the name.. unless you're using an existing database/table?
...
# models/classes in python are singular AND camel cased (99.9%)
# django has a standard that they normally postfix forms with "Form" at the end of the class (no matter if it's a ModelForm or regular Form)
class ProcurementOperationRecordForm(forms.ModelForm)
class Meta:
model = Replenishment
fields = ('id', 'quantity', 'net_amount', 'supplier', 'sell_price')
# I would remove the "id", the client shouldn't care or know about it..
Now to create and update. (This would live inside a view)
# creating?
form = ProcurementOperationRecordForm(data=request.POST)
if form.is_valid():
form.save()
return redirect(..) or render(..)
# updating?
replenishment = Replenishment.objects.get(id='...something')
form = ProcurementOperationRecordForm(data=request.POST, instance=replenishment)
if form.is_valid():
form.save()
return redirect(..) or render(..)
This is just a general idea. You can try something like this.
First get the user input values of quantity and supplier like this from the valid form.
quantity = form.cleaned_data.get('quantity')
supplier = form.cleaned_data.get('supplier')
Then you can update your replenishment model
replenishment.objects.filter(Supplier=supplier).update(StockOnOrder=quantity)

How to name model instances based on a value chosen in ModelChoiceField in Django?

I have problem with Django. I have class Typy and I want to name instances of this class based on username and field match_to_bet which is ModelChoiceField and is generated from base.
class Typy(models.Model):
users = (('user_1', 'user_1'),
('user_2', 'user_2'))
user = models.CharField(max_length=10, blank=True, choices=users)
mecz = models.ForeignKey('Mecz', on_delete=models.CASCADE, default=0)
choice = Mecz.objects.values()
match_to_bet = ModelChoiceField(queryset=choice, empty_label=None)
bet_home = models.BigIntegerField()
bet_away = models.BigIntegerField()
def __str__(self):
return str(self.user) + '_' + str(self.match_to_bet.__str__())
So far I get name with object's adress and have no idea how to change code to get names 'user'_'option chosen in match_to_bet'
current instances names
ModelChoiceField is used in Forms not in Models.
You want CharField or IntegerField with choice attribute.
Then you can do get_fieldname_display()

Categories