I have 2 models like such:
class Volunteer(models.Model):
first_name = models.CharField(max_length=50L)
last_name = models.CharField(max_length=50L)
address = models.CharField(max_length=100L)
city = models.CharField(max_length=100L)
state = models.CharField(max_length=2L)
zip = models.CharField(max_length=5L)
skype = models.CharField(max_length=50L)
email = models.CharField(max_length=50L)
age = models.IntegerField(max_length=2L)
phone_mobile = models.CharField(max_length=50L)
phone_home = models.CharField(max_length=50L)
gender = models.CharField(max_length=1)
class Assignment(models.Model):
volunteer = models.ForeignKey(Volunteer)
department = models.ForeignKey(Department)
role = models.ForeignKey(Role)
location = models.CharField(max_length=100L, blank=True, null=True)
I'm trying to get all volunteers as well as their assignment. The following works:
volunteers = Volunteer.objects.all().order_by('last_name')
for volunteer in volunteers:
assignment = Assignment.objects.get(volunteer=volunteer)
volunteer.assignment = assignment
But is there a more Django way of doing it?
In your current model structure, each volunteer can have multiple assignments. So there is no such thing as "the" assignment for a volunteer. Perhaps you meant to use a OneToOneField instead of a ForeignKey, in which case you would automatically get an "assignment" accessor from Volunteer, making your loop redundant.
You can get all assignements of volunteer by using FOO_set, more here in docs:
volunteer.assignement_set.all()
Related
I have a Django models where I have this :
class Patient(models.Model):
FirstName = models.CharField(max_length=264)
LastName = models.CharField(max_length=264)
Address = models.TextField(blank=True)
Telephone_no = models.CharField(max_length=100,blank=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,related_name='patients')
class UploadedImages(models.Model):
patient = models.ForeignKey(Patient,on_delete=models.CASCADE,related_name='images')
original = models.ImageField(upload_to = user_directory_path, validators=[validate_file_extension],verbose_name = 'Image')
enhanced = models.ImageField(upload_to=analyses_directory_path, blank=True)
segmented = models.ImageField(upload_to=analyses_directory_path, blank=True)
class Processed(models.Model):
uploaded_image = models.ForeignKey(UploadedImages,on_delete=models.CASCADE,related_name='processed')
pre_analysed = models.ImageField(upload_to=analyses_directory_path, blank=True)
analysedimage = models.ImageField(upload_to=analyses_directory_path, blank=True)
so I want to make queries based on the current user which is user = request.user this is possible in the patient model case as I can make Patient.objects.filter(user=user)
but i can't make it the other 2 models
is there any idea how I can do this?
I didn't add the user FK as I thought I wouldn't need it but now I do?
do i need to add it ? can I make a query without adding the field ?
If you want to query across relationships, Django has explicit syntax for that. For example, to get all the UploadedImage objects for a specific user, use UploadedImage.objects.filter(patient__user=user).
Patient.objects.filter(user=user) returns a queryset, to get patient by user, assuming one Patient has only one user:
patient = Patient.objects.filter(user=user).first()
then you can do:
uploaded_images = patients.images.all()
for image in uploaded_images:
processed = image.processed.all()
I'm using elasticsearch_dsl to help with interfacing with elasticsearch and this is the model I currently have and I'm trying to recreate as a DocType:
class HouseIndex(DocType):
house_type = String()
#people
sold = Boolean()
built_datetime = Date()
#alerts
# associated_locations
hash = String()
class House(models.Model):
house_type = models.ForeignKey(HouseType, db_index=True,
on_delete=models.CASCADE)
people = models.ManyToManyField(to='Person', db_index=True,
through='PersonToHouseMap')
sold = models.BooleanField(default=False)
built_datetime = models.DateTimeField()
alerts = models.ManyToManyField(Alert)
associated_locations = models.ManyToManyField(to='Location')
hash = models.CharField(max_length=64, unique=True, null=True)
objects = HouseManager()
But I'm not sure what to do when it's a ManyToMany field. Such as with people, alerts, and associated locations.
It really depends on what you wish to query for, but I'd probably use a Nested field containing a list of the Location objects. You can see something similar in my example repo here - https://github.com/HonzaKral/es-django-example/blob/master/qa/models.py#L48
I have following two models.
class TeacherInfo(models.Model):
name = models.CharField(max_length=200)
school_id = models.ForeignKey('admin_app.School')
timestamp = models.DateTimeField(auto_now=True, blank=True)
class AssignedSheetStatus(models.Model):
level = models.ForeignKey('admin_app.Levels')
subject = models.ForeignKey('admin_app.Subject')
set = models.ForeignKey('admin_app.Set')
teacher = models.ForeignKey('teacher.TeacherInfo')
assigned_count = models.PositiveIntegerField(default=0)
corrected_count = models.PositiveIntegerField(default=0)
timestamp = models.DateTimeField(auto_now_add=True)
Now I want to join these two tables such that I have name from TeacherInfo and sum of assigned_count , corrected_count.
Normally for one teacher I would do :
AssignedSheetStatus.objects.filter(teacher__id=teacher_id).aggregate(Sum('assigned_count'), Sum('corrected_count'))
But here I want this for all of the teachers in TeacherInfo.
What is the best way to achieve this?
You can do it the other way arround. Annotate over the TeacherInfo:
TeachInfo.objects.annotate(Sum('assignedshetsstatus__assigned_count'), Sum('assignedsheetstatus__corrected_count'))
I want to find the number of articles for which a specific user has created articlehistory records.
The models for that look like this:
class Article(models.Model):
"""The basic entity of this app.)"""
documentID = models.CharField(blank=True, max_length=1000)
cowcode = models.IntegerField(blank=True, null=True)
pubdate = models.DateField(default=datetime.datetime.today)
headline = models.CharField(blank=True, max_length=1500)
source = models.CharField(blank=True, max_length=5000)
text = models.TextField(blank=True, max_length=1000000)
assignments = models.ManyToManyField(Assignment)
class Meta:
ordering = ['pubdate']
def __unicode__(self):
return self.headline
class ArticleHistory(models.Model):
"""(Modelname description)"""
article = models.ForeignKey(Article, related_name='Article History')
coder = models.ForeignKey(User, related_name='Article History')
last_updated = models.DateTimeField(default=datetime.datetime.now)
def __unicode__(self):
return self.last_updated
The way I'm trying to do this at the moment is like this:
assignment.finished_articles = Article.objects.filter(cowcode=country).filter(pubdate__range=(start_date,end_date), articlehistory__coder=request.user.id).count()
This doesn't work, however and exhibits another weird behaviour:
I try to do this:
for assignment in assignments:
country = assignment.country.cowcode
start_date = assignment.start_date
end_date = assignment.end_date
articles = Article.objects.filter(cowcode=country).filter(pubdate__range=(start_date,end_date)).select_related()
assignment.article_num = articles.count()
#assignment.finished_articles = Article.objects.filter(cowcode=country).filter(pubdate__range=(start_date,end_date), articlehistory__coder=request.user.id).count()
This works fine, unless I try to include finished_articles, then article_num gets shortened to one result.
It would be really great if anyone has a pointer to who to solve this.
Make use of reverse relation of ForeignKey created by parameter related_name:
Rename attribute related name to "article_history_set".
Now, it gives you easy pointer: user.article_history_set is a set of Article History objects where coder is set to this user.
Then you can find which article it is related to by doing article_history.article.
At the end, you have to get rid of repetition and get length of that list.
Here you have more about related_name attribute: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.related_name
I'm trying to pass a 'group' as an extra field using importer-option from django-adaptors but I'm getting the following error...
add() argument after * must be a sequence, not Group
ContactCSVModel.import_data(data=self.filepath, extra_fields="1")
This is my CsvModel...
CsvModel.py
class ContactCSVModel(CsvModel):
first_name = CharField()
last_name = CharField()
company = CharField()
mobile = CharField()
groups = DjangoModelField(Group)
class Meta:
delimiter = "^"
dbModel = Contact
update = {
'keys': ['mobile']
}
model.py
class Contact(models.Model):
"""
Stores all contacts.
"""
first_name = models.CharField(max_length=60)
last_name = models.CharField(max_length=60)
company = models.CharField(max_length=100,blank=True)
mobile = models.IntegerField(max_length=20)
active = models.BooleanField(help_text="States if pet type is active/selectable.")
modified = models.DateTimeField(null=True, auto_now=True, help_text="Shows when object was modified.")
created = models.DateTimeField(auto_now_add=True, help_text="Shows when object was created.")
#FK
groups = models.ManyToManyField(Group, related_name='contacts')
Looking at the project on git (below), could there be any issue with the project and many2many fields, maybe, if so how to fix? or is it my code?
https://github.com/anthony-tresontani/django-adaptors/blob/master/adaptor/model.py#L436
At the moment django-adaptors doesn't support ManyToManyFields. As there is more and more requests about it, I am going to integrate it soonish.
If you want to workaround that, you should work in 2 steps.
The first one would be to create a python object by using a simple CSVModel by removing:
dbModel = Contact
Unfortunately, you would also have to do the update logic manually.
Then you would need to explicitly create the django instance by doing something like:
contact = Contact.objects.create(first_name = csv_object.first_name, ....)
contact.groups.add(csv_object.group)
Hope that helps