Django - Many to Many Field Ordering Issue - python

class Sandeep(models.Model):
model_id = models.CharField(max_length=200, unique=True)
processors2 = models.ManyToManyField(ConfiguratorProduct,blank=True,
related_name="processors2", verbose_name="Processors2")
model_sk= models.CharField(max_length=200, unique=True)
model_dk = models.CharField(max_length=200, unique=True)
model_pk = models.CharField(max_length=200, unique=True)
models.DateTimeField(auto_now_add=True).contribute_to_class(
Sandeep.processors2.through, 'date_added2')
The above is my model and I am using processors2 as a Many to many Field. I want to save many to many field in the same order which i am adding to Sandeep from django Admin but my order get shuffled by the default id of ConfiguratorProduct[Manyto many relation model]
I tried using the above statement and successfully added one new field timestamp but not able to get the data into django admin UI as per the time-stamp.
I have checked so many solutions but not able to find out the best way to display many to many field in the same order which I am adding to the Model.

Related

Error while changing a Char field to Array Field in Django

I am trying to change a existing CharField in a django model (it also allows null and contains null values in db currently)
now I am trying to change it to an Array Char Field, but it throws the below error
"django.db.utils.IntegrityError: column "tags" contains null values"
From
tags= models.CharField(max_length=255, blank=True, null=True)
To
tags = ArrayField(models.CharField(max_length=255, blank=True, null=True))
I have selected option 2 while before running migrate
In this option 2 you selected, you were asked to select a default value yourself, right?
Add a default attribute to your model's field. The existing null values will be turned into that value, for instance:
tags = ArrayField(models.CharField(max_length=255, blank=True, null=True, default=[]))

Django models' best solution for this reverse ForeignKey

I'm making a personal project to manage restaurants.
Two of my models are facing a problem, these models are DiningRoom and Table.
DiningRoom is the representation of any area that the restaurant could have (e.g. we could have one area inside and other area in the terrace of the building).
And in every DiningRoom we can set a layout of Tables.
So, the more object-oriented way I find to map this is by many-to-one relationship (ForeignKey). Since one DiningRoom can have many Tables, and one Table can be only in one DiningRoom. Right?
So my models are:
class DiningRoom(models.Model):
account = models.ForeignKey(Account, on_delete=models.CASCADE, null=False)
name = models.CharField(max_length=50, null=False, blank=False)
rows = models.IntegerField(max=15, null=False)
cols = models.IntegerField(max=15, null=False) # rows and columns are for the room's grid layout.
class Table(models.Model):
row = models.IntegerField(max=15, null=False) # The row in the room's grid where the table is at.
col = models.IntegerField(max=15, null=False) # the column in the room's grid where the table is at.
dining_room = models.ForeignKey(DiningRoom, on_delete=models.CASCADE, null=False) # Here is the problem.
The problem is that when I am querying DiningRooms of the account in the view, I need to fetch also the Tables that are related to each DiningRoom in the queryset result.
def dining_rooms(request):
try:
account = Account.objects.get(id=request.session['account_id'])
except Account.DoesNotExists:
return response(request, "error.html", {'error': 'Account.DoesNotExists'})
dining_rooms = DiningRoom.objects.filter(account=account)
But also I need the Tables of the results in dining_rooms!
I found two possible solutions but none seem to be "correct" to me. One is to make a Many-to-many relationship and validate that any Table is only in one DiningRoom in the view. And the second and worse one could be fetching the Tables once for each DiningRoom obtained in the queryset (but imagine a restaurant with 5 or 6 different areas (DiningRooms), it would be needed to fetch the database six times for every time).
Doing it in vice-versa and fetching all the Tables and select_related DiningRooms is not possible since it's possible to have a DiningRoom with no Tables in it (and in this case we will have missing DiningRooms).
What could be the best way to handle this? Thanks!
You can use the related_name or relationships backwards, an acceptable solution would be to create a method in the DiningRoom model that is called associated_tables() and return using the related_name (modelname_set, in this case it would be table_set). It is the name of the lowercase child model followed by the suffix _set
class DiningRoom(models.Model):
#your fields
def associated_tables(self):
return self.table_set.all()
In addition, this video tutorial could clear your days and give you a better idea about reverse relationships:
https://youtu.be/7tAZdYRA8Sw

onetoone database relation between two tables?

I have 4 tables already exist in system.
Account
Project
document
Catalog
There are many Accounts in the system and each Account many have many Projects, each project have many documents.
[Current system not handle same project name in a different Accounts]
catalog Table:
class catalog(models.Model):
catalog_name = models.TextField(blank=True, null=True)
documents = models.ManyToManyField(document, blank=True, null=True)
Current system map documents of any project in the Catalog table.
We create catalog_name by project_name and add documents in the document
So Project name can not be repeated.
Project Table:
class Project(models.Model):
FK_Account = models.ForeignKey(Account, blank=True, null=True)
Project_ID = models.TextField(blank=True, null=True, db_index=True)
Project_Name = models.TextField(blank=True, null=True, db_index=True)
document Table:
class document(models.Model):
uid = models.TextField(blank=True, null=True,db_index=True)
Code to get Project documents:
def getAllProjectDocument(self, project_obj, current_selected_option='All'):
""" Returns All Project Documents. """
docs = []
cat_obj_list = catalog.objects.filter(catalog_name = project_obj.Project_Name + "-user-catalog")
if cat_obj_list:
catobj = cat_obj_list[0]
if current_selected_option=="All":
docs = catobj.documents.filter(status=2)
else:
docs = catobj.documents.filter(status=2, publish_status=int(current_selected_option))
return docs
Note: status 2 means document is any on project.
There are 950000 documents and 300000 projects in the system. If I have to get project documents of the of all project then I have to query on the catalog table for each project i.e. 300000 time and again do filtering in according to search and then add query set objects to python list and pass to template after finishing for loop
So for loop is running for 300000 times then query on catalog for same count i.e. 300000 and filter again same count i.e. ``300000` . So apache memory is increases.
I come with following idea : This is migration of Database.
I am going to create table which have one to one mapping og project and document.
There are are 4 types of document- 1. Private, 2. Project, 3. Library, 4. Delete document.
class Project_Document(models.Model):
FK_Project = models.ForeignKey(Project, blank=True, null=True)
FK_Dcoument = models.ForeignKey(document, blank=True, null=True)
So is **onetoone mapping is correct or anyone have different way to do this?**
Your ProjectDocument table is really just a many-to-many relationship, exactly as you already have between Catalog and Document. I don't think adding another one would really help, especially as you would then have to ensure the two relationships are kept in sync.
Instead you should add the missing relationship directly between Catalog and Project; I can't tell from the code whether that should be a one-to-many (ForeignKey) or one-to-one, and if the former which direction it should go. But assuming each Project has multiple Catalogs, you would add a ForeignKey on Catalog pointing at Project; then you could get all the Documents for a Project with one query:
project_docs = Document.objects.filter(catalog__project=my_project)
Note also you have some big inefficiencies in your table; you seem to be using TextFields throughout, which are stored as blobs in the database, and therefore have a massive overhead. You should be using CharFields for things like IDs and names; TextFields are only for large blocks of text such as the body content of a document itself.

Create a view/template that allows for user selected date filtering that includes Sum totals for child objects?

I've got two models along these lines:
class User(models.Model):
name = models.CharField(max_length=50, blank=False)
class Transaction(models.Model):
user = models.ForeignKey(User, blank=False)
description = models.CharField(max_length=50, blank=False)
total = models.DecimalField(default=0, decimal_places=2)
date = models.DateField(blank=True)
year = models.CharField(max_length=4)
type = models.CharField(max_length=1, db_index=True, choices=(
('C', 'Cash'),
('V', 'Visa'),
('A', 'Amex'),
))
I'm trying to come up with a view/template, that will allow me to display an html table/report showing each user along with the totals for each type of transaction. i.e.
User Visa Cash Amex Total
User1 $50 $75 $100 $225
This first report seems easy, a list report returning a queryset of the Users, and in the User model I created separate functions to return a total for each type of transaction (as a reverse ForeignKey), like this:
def value_visa(self):
value = self.transaction_set.filter(user=self,type__in=('Visa')).aggregate(Sum('total'))
return value['total__sum']
def value_all(self):
value = self.transaction_set.filter(user=self).aggregate(Sum('total'))
return value['total__sum']
I understand that it is likely not an ideal solution, but it's worked.
However, now I'm trying to filter the transactions included in the summary table by date (or by the string year field) and I can't quite figure out how to do it. The function method I designed would need an argument to limit the date to a specific date (which can't be provided in a template), or if I prefetch_related for the transactions (which isn't currently possible without a dev patch), I can't do the sums in the template anyway nor can I figure out how to return a queryset that includes the users and the sum totals. The date can either be provided in the URL or as a user selection on a form, doesn't matter to be very much.
Any ideas? I've been pulling my hair out with this for a while now!
Thanks in advance for any ideas!
Edit:
I worked this out in a get_context_data method for the view:
users = User.objects.annotate(transactions=Count('transaction')).exclude(transactions=0).order_by('name')
for u in users:
totals = Transaction.objects.filter(user=u,year='2012').values('type').annotate(total=Sum('total'))
With this totals becomes a dicts of the totals for each of the different values of type - so that's perfect. But, I'm not sure how to get both of those to a template - users being a QuerySet and an array of totals (since there would be one for every item in users including some that'd have no values).
Just to close the loop on this, I ended up doing a couple of separate queries in the view and then ran through a for loop to merge them into a single dict and passed that to the template. A bit ugly... but it worked.

Django ImageField issue

I have a similar model
Class Student(models.Model):
"""A simple class which holds the basic info
of a student."""
name = models.CharField(max_length=50)
age = models.PositiveIntegerField()
photo = models.ImageField(upload_to='foobar', blank=True, null=True)
As we can see photo field is optional. I wanted all the students who have their images saved in the college DB. For that i did this
>>> Student.objects.exclude(photo__name=None)
But i am getting this error :
FieldError: Join on field 'photo' not permitted.
So, How can i extract all those students having their photos?
Any sort of help regarding this would be appreciated.
Thanks in advance.
It doesn't work because field lookups only work on other models. Here, name is an attribute on the return value of your photo field.
Try this instead:
Student.objects.exclude(photo__isnull=True)
It is preferred to use isnull instead of comparing equality to None.
EDIT:
Jeff Ober's suggestion:
Student.objects.exclude(photo='')
He says filtering is performed on the actual values stored in DB. In a file field's case the path to the file.

Categories

Resources