I'm trying to create an API using the REST Framework. I ran into a little problem. I want to be able to get a list of events for a specific user by sending a request to the API. Is there a possibility to check if the User sending the request is in the team the event belongs to when an event list is requested?
class Teams(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(max_length=1000, blank=True)
Users = models.ManyToManyField(User, blank=True)
class Event(models.Model):
created = models.DateTimeField(auto_now_add=True)
eventTime = models.DateTimeField()
title = models.CharField(max_length=100, default='')
description = models.TextField(max_length=1000, blank=True)
group = models.ForeignKey(Teams, on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
those are the realtionships between the models i implemented so far
You can do that by overwriting .get_queryset(). This should do the trick:
class EventList(generics.ListAPIView):
def get_queryset(self):
#
return Event.objects.filter(group__users=self.request.user)
Querying many-to-many fields is (in my opinion) not very intuitive.
Event.objects.filter(group__users=self.request.user) basically means "get all events that have a group/team that contain the current user".
Related
I have a model to capture comments from a user, DocumentComment. The comments are tied to a particular document in the database, and created/edited/displayed on the page that displays that particular document:
class DocumentComment(Model):
"""
Captures a user's comment about a document
"""
document_id = models.ForeignKey(Document, on_delete=models.CASCADE, verbose_name="document file name", related_name='document')
user = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.TextField('comment', blank=True)
moderated = models.BooleanField(default=False)
added_to_description = models.BooleanField(default=False)
marked_for_deletion = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True, editable=False, verbose_name="date created")
updated = models.DateTimeField(auto_now=True, editable=False, verbose_name="last update")
I now find I need to record comments based on other objects displayed on different pages in the site, e.g. albums (collections of document) is a page and word clouds (derived from all the words in various documents) is another page. Since these new comments are not tied to one document, but a collection of documents, I don't think they should be added to the DocumentComment model for every document_id in the collection. I wouldn't necessarily want the comments on a collection to be displayed on the page with one of the documents in that collection.
Which approach is better (django-yy or pythonic or idiomatic or by whatever standard you choose):
create separate models as above for each display object (i.e. word clouds, albums, maybe more?)
keep adding foreign keys to the various objects to the DocumentComment model and adding on_delete=models.SET_NULL, blank=True, null=True to each of the foreign key fields
Also, are there some hidden gotchas about option #2 that I have not thought of?
Thanks!
Mark
Model Abstraction is the solution
Class Comment(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
comment = models.TextField('comment', blank=True)
moderated = models.BooleanField(default=False)
added_to_description = models.BooleanField(default=False)
marked_for_deletion = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True, editable=False, verbose_name="date created")
updated = models.DateTimeField(auto_now=True, editable=False, verbose_name="last update")
Class Meta:
abstract = True
Class DocumentComment(Comment):
document_id=Models.ForeignKey()
Class AlbumComment(Comment):
album_if = Models.ForeignKey()
I've got two models. Event and Usercart.
class UserCart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
class Event(models.Model):
order = models.ForeignKey(UserCart, on_delete=models.CASCADE, null=True, blank=True)
start_time = models.DateTimeField()
I'd like to develop a queryset of UserCart instances where there is a related event that is in the past (based on that event's start time)
pastcarts = UserCart.objects.filter(????)
Thanks for your help!
This should be as easy as:
pastcarts = UserCart.objects.filter(event__start_time__lt=<whatever_dt_you_prefer>)
You can read more in docs - check for reverse foreign key filtering.
Background
I'm storing data about researchers. eg, researcher profiles, metrics for each researcher, journals they published in, papers they have, etc.
The Problem
My current database design is this:
Each Researcher has many journals (they published in). The journals have information about it.
Likewise for Subject Areas
But currently, this leads to massive data duplication. Eg, the same journal can appear many times in the Journal table, just linked to a different researcher, etc.
Is there any better way to tackle this problem? Like right now, I have over 5000 rows in the journal column but only about 1000 journals.
Thank you!
EDIT: This is likely due to the way im saving the models for new data (mentioned below). Could anyone provide the proper way to loop and save hashes to models?
Model - Researcher
class Researcher(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
scopus_id = models.BigIntegerField(db_index=True) # Index to make searches quicker
academic_rank = models.CharField(max_length=100)
title = models.CharField(max_length=200,default=None, blank=True, null=True)
salutation = models.CharField(max_length=200,default=None, blank=True, null=True)
scopus_first_name = models.CharField(max_length=100)
scopus_last_name = models.CharField(max_length=100)
affiliation = models.CharField(default=None, blank=True, null=True,max_length = 255)
department = models.CharField(default=None, blank=True, null=True,max_length = 255)
email = models.EmailField(default=None, blank=True, null=True)
properties = JSONField(default=dict)
def __str__(self):
return "{} {}, Scopus ID {}".format(self.scopus_first_name,self.scopus_last_name,self.scopus_id)
Model - Journal
class Journal(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
researchers = models.ManyToManyField(Researcher)
title = models.TextField()
journal_type = models.CharField(max_length=40,default=None,blank=True, null=True)
abbreviation = models.TextField(default=None, blank=True, null=True)
issn = models.CharField(max_length=50, default=None, blank=True, null=True)
journal_rank = models.IntegerField(default=None, blank=True, null=True)
properties = JSONField(default=dict)
def __str__(self):
return self.title
How I'm currently saving them:
db_model_fields = {'abbreviation': 'Front. Artif. Intell. Appl.',
'issn': '09226389',
'journal_type': 'k',
'researchers': <Researcher: x, Scopus ID f>,
'title': 'Frontiers in Artificial Intelligence and Applications'}
# remove researchers or else create will fail (some id need to exist error)
researcher = db_model_fields["researchers"]
del db_model_fields["researchers"]
model_obj = Journal(**db_model_fields)
model_obj.save()
model_obj.researchers.add(researcher)
model_obj.save()
Here is how it works :
class Journal(models.Model):
# some fields
class Researcher(models.Model):
# some fields
journal = models.ManyToManyField(Journal)
Django gonna create a relation table :
Behind the scenes, Django creates an intermediary join table to represent the many-to-many relationship
So you'll have many rows in this table, which is how it works, but journal instance and researcher instance in THEIR table will be unique.
Your error is maybe coming from how you save. Instead of :
model_obj = Journal(**db_model_fields)
model_obj.save()
Try to just do this:
model_obj = Journal.objects.get_or_create(journal_id)
This way you'll get it if it already exists. As none of your fields are unique, you're creating new journal but there's no problem cause django is generating unique ID each time you add a new journal.
I've implemented a messaging system:
class Message(models.Model):
user = models.ForeignKey(User, unique=False, related_name = 'messages')
conversation = models.ForeignKey('Conversation', related_name = 'messages')
body = models.TextField(max_length=750)
reads = models.ManyToManyField(User, related_name='read_messages', null=True, blank=True)
# Other
date_created = models.DateTimeField(auto_now=False, auto_now_add=True, blank=True)
date_modified = models.DateTimeField(auto_now=True, auto_now_add=False, blank=True)
class Conversation(models.Model):
participants = models.ManyToManyField(User, related_name='conversations')
type = models.CharField(max_length=1, default="D", choices=config.CONVERSATION_TYPE_OPTIONS)
Using Django Rest Framework, I'd like to order a conversation by the last message.
class ConversationFilter(filters.BaseFilterBackend):
"""
Filters to only show by current user
"""
def filter_queryset(self, request, queryset, view):
return queryset.filter(
participants=request.user,
).order_by('-messages__date_created')
However once I add the order_by method, the queries are no longer distinct. Adding distinct() does not work either. What is going on here?
You have a one to many relationship between Conversation and Message.
When you join the message table into the Conversation query (which happens when you add the order_by clause using messages), then you will get multiple Conversation entries, one for each message.
I have these Models all of which have PointField:
class Place(models.Model):
title = models.CharField(max_length=75, verbose_name='Заголовок')
category = models.ForeignKey(PlaceCategory, verbose_name='Категория')
...
point = geomodels.PointField(geography=True, blank=True, null=True)
...
class Event(models.Model):
title = models.CharField(max_length=75, verbose_name='Заголовок')
address = models.CharField(max_length=255, blank=True, null=True, verbose_name='Адрес')
city = models.ForeignKey(City, verbose_name='Город')
...
point = geomodels.PointField(blank=True, null=True)
...
class Meeting(models.Model):
title = models.CharField(max_length=75)
participants = models.ManyToManyField(User, related_name='participating_meetings')
...
point = geomodels.PointField(blank=True, null=True)
...
In project I have /points API url. By this url I want to return filtered set or all the points to show them on map.
I checked DRF documentation, there is example how to build Serializer for one Model, but how do I build the API view for these multiple models?
This kind of use case is typical of where you'd need to drop the default auto generated things (serializer / view) and roll your own. I would gather the data by myself, run them through a PointSerializer - might be optional - which would inherit from Serializer and return the result.