I am trying to write a program for registering plates. However we have three types of plate and i've created a choice field for these three. the thing i wanna do is that i need to create a OneToOne field which it's given model is based on the data of the choice filed for example if the user chose 1 i need to have OnetoOne field to CarPlate if 2 OneToOne field to MotorPlate and so on....
VEHICLE_CHOICES = (
("1", "سواری ملی"),
("2", "سواری منظقه ازاد انزلی"),
("3", "موتور سیکلت"),)
class Vehicle(models.Model):
vehicle_type = models.CharField(
max_length=3,
choices=VEHICLE_CHOICES,
blank=False
)
# below is an example of what i want to do
if vehicle_type == 1 :
plate_car = models.OneToOneField(CarPlate, on_delete=models.CASCADE, related_name="savari", blank=True)
elif vehicle_type == 2:
plate_anzali = models.OneToOneField(AnzaliPlate, on_delete=models.CASCADE, related_name="mantaqe", blank=True)
else:
plate_motor = models.OneToOneField(MotorPlate, on_delete=models.CASCADE, related_name="motor", blank=True)
the code above works but it doesn't give me the right answer.
Apparently these kind of settings are not allowed in models, but you can write a global field for every one of them and then in the front-end part of the project you can only get the fields that you want for the chosen choice field
Related
I'm trying to create an Django ORM query to replace a really messy raw SQL query i've written in the past but i'm not sure if Django ORM can let me do it. I have three tables:
contacts
custom_fields
custom_field_data
What I'm hoping to be able to do with the ORM is create an output as if i've queryied one single table like this:
Is such a thing possible with the ORM?
EDIT:
The models are:
class Contact(models.Model):
company = models.ForeignKey(Company, on_delete=models.PROTECT, null=True, blank=True)
class CustomField(models.Model):
name = models.CharField(max_length=100)
company = models.ForeignKey(Company, on_delete=models.PROTECT, null=False, blank=False)
class ContactCustomFieldValue(models.Model):
custom_field = models.ForeignKey(CustomField, on_delete=models.PROTECT, related_name='contact_values')
contact = models.ForeignKey(Contact, on_delete=models.PROTECT, related_name='custom_field_values', null=True)
value = models.TextField(null=True)
Solved this one in large part thanks to Ken from the Django forums.
The solution he provided looked like this:
subquery1 = Subquery(ContactCustomFieldValue.objects.filter(contact=OuterRef('id'), custom_field_id=1).values_list('value'))
subquery2 = ...
subquery3 = ...
subquery4 = ...
contact_list = Contact.objects.filter(...).annotate(field1=subquery1, ...)
I've built on it to fit my needs but as a starting point this was perfect
I Have a Invoice system where employee or staff can create invoice and can add multiple product and quantity for the specific customer . as i am using mysql i cant take json data or an array data .so i was taking the quantity and price( after discount and other modificaion) as a string and then when showing or printing the invoice i used regex to find the quantity and price .i added product ids in a manytomay field from where i am getting the product name and selling price. while showing the data on printing page in when i use zip the products are showing as the id of the product so i want to retrive the data the way it is being saved . or could you tell me any way to do it more easier way?
Here is my models.py
class Invoice(models.Model):
customers = models.ForeignKey(Customer, on_delete=models.CASCADE)
products = models.ManyToManyField(Product)
total = models.FloatField()
date = models.DateField(auto_now_add=True)
amounts = models.CharField(max_length=500, default="00")
quantity = models.CharField(max_length=500, blank=True)
def save(self, *args, **kwargs):
if not Invoice.objects.count():
self.id = 20210001
else:
self.id = Invoice.objects.last().id + 1
super(Invoice, self).save(*args, **kwargs)
Here is my views.py of printing page function
def final_billing(request, id=None):
pk = id
obj = Invoice.objects.get(id=pk)
products = obj.products.all()
customer = Customer.objects.get(id=obj.customers.id)
amn = obj.amounts
qt = obj.quantity
list_of_comma = re.findall("[\d+.+\d]+", amn)
amnts = [float(n) for n in list_of_comma]
list_of_quantity = re.findall('[0-9]+', qt)
qty = [int(n) for n in list_of_quantity if n.isdigit()]
products = list(products)
both = zip(products,amnts,qty)
return render(request, 'finalbill.html',{'bills': obj, "due": customer, "both": both})
I want it to be retrieved the product objects in the sequence of it was saved
The query can only be sorted with a specific field, Django cannot guess otherwise, so in your case the best case is to sort your products by the date they were created, for example :
obj.products.all().order_by("created")
This suppose that you have a "created" field that is added each time a product is save in your database.
Another way of doing it is to specify the through option, from the documentation :
you can use the through option to specify the Django model that represents the intermediate table that you want to use.
The most common use for this option is when you want to associate extra data with a many-to-many relationship.
The through table contains an the primary key of the relation, you can use that to retrieve the sequence in which your objects were added.
for example :
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=50)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
Person,
through='Membership',
through_fields=('group', 'person'),
)
class Membership(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
inviter = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="membership_invites",
)
invite_reason = models.CharField(max_length=64)
Through Field
Hello I have a problem that I want to link foreign key to model's related object in other words I want to link foreign key to not loaded object's fields.
class Category(models.Model):
...
filter_option_content_type = models.ForeignKey(ContentType, on_delete=models.SET_NULL, limit_choices_to=(
models.Q(app_label='catalog', model='FrameSize') |
models.Q(app_label='catalog', model='ShoeSize') |
models.Q(app_label='catalog', model='ClothSize')
), null=True)
...
class Product(models.Model):
...
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
...
class ProductItem(models.Model):
...
model = models.ForeignKey(Product, verbose_name='Модель', on_delete=models.CASCADE, related_name='productitem')
size = models.ForeignKey('model.category.filter_option_content_type', on_delete=models.SET_NULL, null=True)
...
And sure i got this error:
ValueError: Invalid model reference 'model.category.filter_option_content_type'. String model references must be of the form 'app_label.ModelName'
is it possible to do relation like this wtihout using GenericForeignKey instead of ForeignKey?
I think that you don't really need to add an additional relation since you can access the field you want via Product:
item = ProductItem()
size = item.model.category.filter_option_content_type
In case you'd like to query using this field, it would look like:
item = ProductItem.objects.filter(
model__in=Product.objects.filter(
category__in=Category.objects.filter(
filter_option_content_type='<your desired value of size>'
)
)
)
Since the relations are based on Foreign Keys which are indexed - such query shouldn't have a noticeable effect on performance (despite that it may seem a bit awkward)
I'm writing a web application (DRF + Vue.js) where frontend should have an ability to narrow down GET request results via different filters.
For example, I have a model like this:
class Human(models.Model):
first_name = models.CharField(_('first name'), max_length=50, null=True, blank=True)
last_name = models.CharField(_('last name'), max_length=50, null=True, blank=True)
birth_date = models.DateField(_('birth date'), blank=True, null=True)
city = models.ForeignKey('City', on_delete=models.SET_NULL, blank=True, null=True)
phone_number = models.ForeignKey('Contact' on_delete=models.SET_NULL, blank=True, null=True)
#property
def full_name(self):
# Last name + First name
return ' '.join(str(x) for x in (self.last_name, self.first_name) if x)
#property
def is_adult(self):
now = timezone.now()
if self.birth_date:
if now.year - self.birth_date.year - \
((now.month, now.day) < (self.birth_date.month, self.birth_date.day)) >= 18:
return True
return False
Now I have simple CRUD ViewSet where I can use a list of search_fields to search by all needed fields (in my case that's birth_date, city, phone_number and full_name/is_adult). But here next problems arise:
Using search_fields I can do a search only by all fields specified in the ViewSet's search_fields (frontend can't search only by city or other distinct fields if it wants to) - other way I'll need to create a separate ViewSet (and separate URL?) for every combination of fields to filter by. Terrific.
So it looks like the correct decision must be capable of filtering by several GET parameters at once. Ideally - with opportunity to choose exact/icontains/etc comparison method on each query.
That sounds like a work for django-filter but I'm not sure yet.
It's impossible to search/filter by full_name or is_adult because they are dynamic model properties, not usual fields.
So it looks like instead of using model properties I need to use separate QuerySets (Manager methods?) that will do the logic of fiddling with model fields and creating the filtered result.
But for now I didn't find a way to choose different QuerySets in a single ViewSet depending on GET parameters (or how to use search by these complex properties together with simple search from problem 1?).
And I have no understanding if it is possible to provide this kind of search by the same URL as a "simple" search - like site.com/api/people/?city=^New&full_name=John%20Doe (perfectly - with opportunity to document query parameters for OpenAPI schema / Swagger)
So maybe someone knows which is the most elegant way to provide a capability of such complex search with Django/DRF? In which direction should I look?
"full_name" alias needs to be part of your queryset.
You can achieve it by queryset annotation.
In your People view (api/people/ controller) you have to set your queryset to be:
from django.db.models.functions import Concat
from django.db.models import Value
queryset = Human.objects.annotate(fullname=Concat('first_name', Value(' '), 'last_name'))
Also, customize your "filter_backed" to act the way you need.
class PeopleFilterBackend(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
params_serializer = PeopleFilterSerializer(data=request.params)
params_serializer.is_valid(raise_exception=True)
valid_params = params_serializer.data
if full_name := valid_params.get("full_name")
queryset = queryset.filter(full_name__icountains=full_name)
# insert here all of other filters logic
return queryset
PeopleFilterSerializer is your custom params serializer,
You have to specify there all of your accepted params:
from rest_framework import serializers
class PeopleFilterSerializer(serializers.Serializer):
full_name = serializers.CharField() # set required=False if not required
city = serializer.CharField()
I have two model Stock and Trade.
class Stock(models.Model):
name = models.CharField(max_length=15, blank=False, primary_key=True)
price = models.IntegerField(blank=False, editable=True)
class Trade(models.Model):
id = models.AutoField(primary_key=True, auto_created=True, editable=False, )
name = models.ManyToManyField(Stock, related_name='stock_name')
trade_choice = [
(1, 'BUY'),
(0, 'SELL')
]
type = models.CharField(choices=trade_choice, default='BUY', max_length=5)
quantity = models.IntegerField(blank=False, )
price = models.ForeignKey(Stock, on_delete=models.CASCADE, related_name='stock_price')
The problem with Trade.price as foreign key is that, when user select Trade.name as "APPLE" to buy the price will not be of APPLE instead it will be price value of all stock from which user can choose which is wrong. I want to set value of price depending on user stock name for buy or sell.
How can this be achieved?
class Trade(models.Model):
stock_model_obj = models.IntegerField(blank=False, editable=True)
and then you can easily all fields of stock obj easily.
let's say instance is obj of Trade model then you can directly use instance.stock_model_obj.price or instance.stock_model_obj.whatever_field_of_Stock
P.S. You can also use further joins if stock model have other foreign keys
Happy coding