Django update a Foreign Key model using reverse lookup - django

I am working on a Django project and stuck at a problem. My models look like this:
class Products(models.Model):
basket_name = models.CharField(max_length = 5, blank = False)
product_name = models.CharField(max_length = 30, blank = False)
quantity = models.PositiveSmallIntegerField(null = False, blank = False, default=1)
class ShelfProduct(models.Model):
shelf_name = models.CharField(max_length = 15, default="defaultshelf")
products = models.ManytoManyField(Products)
..... other fields....
class KioskShelf(models.Model):
kiosk_name = models.CharField(max_length= 15, default="default")
shelfproduct = models.ManytoManyField(ShelfProduct)
...other fields....
class MapperModel(models.Model):
kioskshelf = models.ForeignKey(KioskShelf, on_delete = models.CASCADE)
...other fields....
I am trying to update the product quantity in Products models for a particular kiosk name and particular shelf. I tried like this:
data = MapperModel.objects.filter(kioskshelf__kiosk_name = 'kiosk1').filter(kioskshelf__shelfproduct__shelf_name = 'Shelf A')
But after this am not sure how to update the quantity in Products table. Am not even so sure if my approach is correct. Please assist me how to do it. Thanks a lot in advance.

You need to go through the Products table. Have you tried:
Products.objects.filter(shelfproduct__shelf_name='Shelf A', shelfproduct__kioskshelf__kiosk_name='kiosk1').update(quantity=<quantity>)

Related

slow process during saving model in database

i want save a list of model in database table but i very slow
when i use save() method for each item it took near 20min
is that a best way to save objects to table
Modles.py
class Part(models.Model):
block = models.CharField(max_length= 2, null= True)
phase = models.CharField(max_length= 3, null= True)
department = models.CharField(max_length= 20, null= True)
type = models.CharField(max_length= 10, null= True)
mark = models.CharField(max_length= 20, null= True)
class Task(models.Model):
name = models.CharField(max_length= 20)
class ProjectTask(models.Model):
project = models.ForeignKey('Project', on_delete= models.CASCADE)
task = models.ForeignKey("Task", on_delete=models.CASCADE)
weight_percent = models.FloatField()
class PartTask(models.Model):
part = models.ForeignKey('Part', on_delete= models.CASCADE)
project_task = models.ForeignKey('ProjectTask', on_delete= models.CASCADE)
progress = models.FloatField(null=True)
views.py
def import_part_task(_project_id):
project_id = _project_id
project_task = ProjectTask.objects.all().filter(project= int(project_id[0]))
part_list = Part.objects.all()
part_task_list = []
for part in part_list:
for task in project_task:
part_task = PartTask()
part_task.part =part
part_task.project_task = task
part_task_list.append(part_task)
#This ACTION TAKES VERY LOG TIME
for part_task in part_task_list:
PartTask.save(part_task)
That makes perfect sense, since saving the database means that you each time query the database. This takes significant time.
You can however boost performance by inserting with bulk_create(..) [Django-doc]:
def import_part_task(_project_id):
project_id = _project_id
project_task = ProjectTask.objects.filter(project= int(project_id[0]))
part_list = Part.objects.all()
part_task_list = [
PartTask(part=part, project_task=task)
for part in part_list
for task in project_task
]
PartTask.objects.bulk_create(part_task_list)
By inserting in bulk, Django will create a query to insert a large amount of objects with a single query, instead of each time making a query for each individual PartTask object. The amount of "round trips" to the database is thus reduced significantly.

View and Template for m2m with Through

In my app i need to store invoices (Invoice) of known products (Product) to calculate points for each seller (User). I'm trying to create form to insert basic invoice data plus inline form with sold products info. To handle it i create model like this:
class Product(models.Model):
group = models.CharField(max_length = 200, blank = False)
mark = models.CharField(max_length = 200, blank = True)
points = models.IntegerField(blank = False)
class Invoice(models.Model):
price = models.FloatField(blank=False)
file = models.FileField(blank=False)
product = models.ManyToManyField(Product, through='Sold')
user = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateField()
date_created = models.DateField(auto_now_add=True)
date_updated = models.DateField(auto_now=True)
class Sold(models.Model):
invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=1)
I tried to manage it via django-admin and it work fine with admin.py:
class ProductTabular(admin.TabularInline):
model = Invoice.product.through
class InvoiceAdmin(admin.ModelAdmin):
inlines = [ProductTabular]
exclude = ('product', )
class Meta:
model = Invoice
admin.site.register(Invoice, InvoiceAdmin)
but i'm unable to create such form in own templates. Please, can you help me with views.py and template to get same result as for the django-admin?
I tried via invoce form with inlineformset_factory for the Sold model, but i can't figure out how to save it. Thanks for any help!

Django syncdb cannot find postgres View for ForeignKey relation

I'm trying to create a ForeignKey relation to a postgres view. This was originally working with a different model but now that I've created a second one it seems unable to create the new table.
The error I'm given is:
DatabaseError: referenced relation "countryzone" is not a table
The Country model is defined as follows:
class Country(models.Model):
code = models.CharField(
db_column = 'countrycode',
primary_key = True,
max_length = 2,
)
name = models.CharField(
max_length = 100,
db_column = 'countryname',
unique = True,
)
language_code = models.CharField(
max_length = 8,
null = True,
)
country_level = models.IntegerField()
latitude = models.DecimalField(
db_column = 'clat',
decimal_places = 3,
max_digits = 8,
null = True,
)
longitude = models.DecimalField(
db_column = 'clong',
decimal_places = 3,
max_digits = 8,
null = True,
)
timezone = models.IntegerField()
zone = models.CharField(max_length=1)
transit_time = models.IntegerField()
## MANAGER
objects = CountryManager()
## META DATA
class Meta:
db_table = 'countryzone'
My new model creates the ForeignKey the following way:
country = models.ForeignKey(
to = 'location.Country',
db_column = 'countrycode',
)
I'm referencing the Country model from a different class without any problems like so:
countrycode = models.ForeignKey(
to = 'location.Country',
db_column = "countrycode",
)
Any ideas where I might be going wrong or what I should look into to find my problem?
Thanks!
the name of table must be location_countryzone.
Looks like syncdb can't handle this on it's own, I needed to use manage.py sqlall to get the correct query and run it myself. Once doing so the table was skipped over on future attempts of syncdb so then I was able to continue using it.

Django-ORM: Illustrate a precise query for the situation

I have 4 models in my project. Which are :
class Company(Group):
address_1 = models.CharField(max_length = 300, blank = True, null = True)
web_site = models.URLField(blank = True, null = True)
office_number = models.CharField(max_length = 20, blank = True, null = True)
class Person(models.Model):
user = models.ForeignKey(User)
company = models.ForeignKey(Company)
class Project(models.Model):
name = models.CharField(max_length = 100)
person = models.ManyToManyField(User, through = 'UserProject')
class UserProject(models.Model):
user = models.ForeignKey(User)
project = models.ForeignKey(Project)
is_owner = models.BooleanField(default = False)
In a view I would want to get
All the projects related to the request.user
The companies that are working on those projects
and the employees of those companies
I have tried writing some code but the queries are not precise. Help would be appreciated!
All projects related to request.user is easy, of course:
Project.objects.filter(person=request.user)
The companies working on those projects necessarily requires you to loop through the projects:
for p in projects:
p.company_set.all()
You have no relationship between User and Company, or any other foreign key on Company for that matter, so I have no idea where the concept of "employee" comes from or how to get that.
Since, this is pretty basic stuff, I'm assuming your issue is with the fact 1*N queries that are generated. In the current version of Django (1.3.1), there's no way to optimize this futher. In Django 1.4, there's prefetch_related that will allow you to select all the companies (and employees) with the Projects. However, it still requires a unique query for each relationship, so 3 total to get projects, companies, and employees. It works like this:
Project.objects.filter(person=request.user).prefetch_related('company')
In the mean time, I've had some success with using django-batch-select, which basically tries to emulate the behavior of prefetch_related.
OK some bugs in your models:
Project has a M2M on User through UserProject, which is fine, except I think you mean for it to have a M2M on Person which has a FK to User
Secondly, you haven't set up any relations to Company. there is no way to do item 2 on your list until that bug is fixed.
Why is Company extending Group? I must be missing something.
There is no Employee model
Example:
class Company(models.Model):
address_1 = models.CharField(max_length = 300, blank = True, null = True)
web_site = models.URLField(blank = True, null = True)
office_number = models.CharField(max_length = 20, blank = True, null = True)
class Employee(models.Model):
user = models.ForeignKey(User)
company = models.ForeignKey(User)
class Project(models.Model):
name = models.CharField(max_length = 100)
employees = models.ManyToManyField(Employee, through = 'EmployeeProject')
companies = models.ManyToManyField(Company)
class EmployeeProject(models.Model):
employee = models.ForeignKey(Employee)
project = models.ForeignKey(Project)
is_owner = models.BooleanField(default = False)
and in the view
# all of the projects for a user (assuming employee field is supposed to M2M to the Employee model
projects = Project.objects.filter(employees__user=request.user)
for project in projects :
# assuming that there was some connection between project and company (there isnt currently, see me list of bugs with your models)
for company in project.companies_set.all() :
# There is no employee model, but if there was
employees = company.employees_set.all()
I have pondered and used some of the solutions enlisted above, but nothing was exact to what I was looking for. For me the following piece of code works well
projects = Project.objects.filter(person = request.user)
user_projects = UserProject.objects.filter(project__in = projects)
for user_project in user_projects:
person = user_project.user.get_profile()
company.append(person.company)
people.append(person)
company = set(company)

Is there a way to filter some model records unrelated with another model in django admin site?

class Town (models.Model):
name = models.CharField (max_length = 150,
verbose_name = _("Human settlement name"),
)
ref_town = models.ForeignKey ('self',
blank = True,
null = True,
verbose_name = _("Superior human settlement"),
help_text = _("Superior human settlement name (for subordinate settlements)"),
)
class CoalMine (models.Model):
name = models.CharField (max_length = 150,
verbose_name = _("Coal mine"),
help_text = _("Coal mine name"))
town = models.ForeignKey (Town,
default = 1,
verbose_name = _("town"))
I have a lot of towns im my data and I need to filter those which are unrelated with coal mines. Is there any solution?
Since Django 1.3 you can override SimpleListFilter to get it to do what you want.