Relational Mapping using Peewee - python

I'm new to relational databases and I'm quite confused on how should I create the models. What I need need to get done is to filter the posts content through the language choice and to do that I need to create a relational database. My doubt comes when deciding how many models(tables) should I have to accomplish this. Here is an example:
models.py
class Post(Model):
timestamp = DateTimeField(default=datetime.datetime.now)
user = ForeignKeyField(
rel_model=User,
related_name='posts'
)
language = TextField()
content = ForeignKeyField(THIS NEEDS TO POINT TO THE LANGUAGE)
class Meta:
database = DATABASE
Is it possible to accomplish something like this? Should I create more than one Post model?
Thank you in advanced.

Have you run through the quickstart guide? Doing so might give you a feel for how to create models and set up relationships:
http://docs.peewee-orm.com/en/latest/peewee/quickstart.html
To answer your immediate question, you can create another table for language, i.e.
class Language(Model):
name = CharField()
class Meta:
database = DATABASE
So all together you'd have (cleaned up a bit):
DATABASE = SqliteDatabase('mydb.db') # or PostgresqlDatabase or MySQLDatabase
class BaseModel(Model):
class Meta:
database = DATABASE
class User(BaseModel):
email = CharField()
# whatever other user fields
class Language(BaseModel):
name = CharField()
# other fields?
class Post(BaseModel):
timestamp = DateTimeField(default=datetime.datetime.now)
user = ForeignKeyField(User, related_name='posts')
language = TextField()
content = ForeignKeyField(Language, related_name='posts')

Related

Automatically create predefined objects in database for ManyToMany?

how would I go about automatically generating a list of objects in the database for DJango?
Example model:
#models.py
class Book(models.Model):
BOOKS = (
('0','Secret Life of Bees'),
('1','Pride and Prejudice')
)
name = models.CharField(max_length=100, choices=BOOKS)
def __str__(self):
return self.name
class Library(models.Model):
librarian = models.OneToOneField(UserProfile, on_delete=models.CASCADE, primary_key=True)
books = models.ManyToManyField(Book)
How would I automatically add all the books to the database so I don't have to manually add them using the admin control panel?
Update! To anyone who doesn't know how to do this, you can call Object.objects.bulk_create(Object([Object(property=propertyInfo),Object(property=propertyInfo)]).

Django prefetch_related in property of inherited model

I am running into an issue with prefetch_related on a property of an inherited model.
In models.py I have:
class Security(models.Model):
name = models.TextField()
...other fields
class Fund(Security):
...other fields
#property
def underlying_security(self):
return self.maps_when_mapped.get().original_security
class SecurityToSecurityMap(models.Model):
original_security = models.ForeignKey(Security, related_name="maps_when_original")
mapped_security = models.ForeignKey(Security, related_name="maps_when_mapped")
and in serializers.py
class UnderlyingSecuritySerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField()
class FundSerializer(serializers.ModelSerializer):
underlying_security = UnderlyingSecuritySerializer(read_only=True, allow_null=True)
class Meta:
model = Fund
fields = ("id", "name", "underlying_security")
Now, I when I am querying fund objects:
queryset = Fund.objects.prefetch_related("maps_when_mapped__original_security")
Django ignores prefetching. Experimented with `Prefetch, tried moving property to the parent - no luck, still getting hundreds on queries. Any way this can be optimised?
I am using Django 2.2 with Postgres 11
UPDATE 1
After looking at the question, I suspect that problem is when I use .get() in property, it is immediately evaluated but then not sure how to fetch it without evaluation

Create identical model in django

I am using django 1.10 with mysql.
I am willing to have two tables in my db with the same fields.
class Ticket(models.Model):
listing = models.ForeignKey(Listing)
ticketId = models.CharField(max_length=32)
dateOfPosting = models.DateTimeField()
seatNumber = models.PositiveIntegerField(null=True, blank=True)
class SoldTicket(models.Model):
### same fields here
What is the best way to do it?
Having two identical tables in your database suggests that you don't need them, a boolean field or some foreign key would most likely do the job.
Hovewer, if you really want to have two identical models, you should look at abstract models.
class AbstractBase(models.Model):
listing = models.ForeignKey(Listing)
ticketId = models.CharField(max_length=32)
...
class Meta:
abstract = True
class Model1(AbstractBase):
pass
class Model1(AbstractBase):
pass
That way Model1 and Model2 will have same fields.

Creating many to many relation with AUTH_USER_MODEL in django via intermediary model

I am trying to create the following models. There is a ManyToMany relation from Entry to AUTH_USER_MODEL via the EntryLike intermediate model.
class BaseType(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
creation_time = models.DateTimeField(auto_now_add=True)
last_update_time = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Title(BaseType):
text = models.CharField(max_length=100)
description = models.TextField()
class EntryLike(BaseType):
entry = models.ForeignKey(Entry)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
class Entry(BaseType):
title = models.ForeignKey(Title, on_delete=models.PROTECT)
text = models.TextField()
user = models.ForeignKey(settings.AUTH_USER_MODEL)
liked_by_users = models.ManyToManyField(settings.AUTH_USER_MODEL, through='EntryLike', through_fields=('entry', 'user'))
Running migrations on the above model scheme throws the error: AttributeError:'str' object has no attribute 'meta'.
Any help in resolving this error would be highly appreciated. Am new to Django & Python, but not to Web Development.
The issue is that settings.AUTH_USER_MODEL is almost certainly not a model instance. It's probably a string that constrains the choices another model can make - settings would be a strange place to leave a model definition.
To do a MTM between the user model and your field above you need need to do:
from django.contrib.auth.models import User
class Entry(BaseType):
title = models.ForeignKey(Title, on_delete=models.PROTECT)
text = models.TextField()
user = models.ForeignKey(User)
def __str__(self):
return self.title
I've added the str function so that it gives a more sensible return when you're manipulating it in admin/shell.
I'd also question whether you need the second set of fields (removed here), as you can use select related between the Entry and EntryLike join table, without any duplication of the fields - you can probably go that way, it's just a bit unnecessary.
Lastly, I'd note that the way I'm using it above just uses the default User object that comes with Django - you may wish to customise it. or extend the base class as you've done here with your own models' base class.
(All of this is predicated on AUTH_USER_MODEL not being a model instance - if it is, can you post the model definition from settings.py? )

Table join using the Django ORM

I'm trying to figure out the Django ORM and I'm getting a little confused on the equivalent of a table join.
Assume I have the three models below, abbreviated for readability. "User" is the out-of-the-box Django user model, "AppUser" is a corresponding model for storing additional profile info like zip code, and "Group" is a collection of users (note that this group has nothing to do with authentication groups). Each AppUser has a one-to-one relationship with each User. Similarly, each AppUser also points to the Group of which that user is member (which could be None).
My task: given a group_id, generate a list of all the member emails.
I know that I can "traverse backward one-level" from Group to AppUser using .appuser_set.all() but I don't know how to go further to fetch the related User and its email without iterating through and doing it in a very DB heavy way like this:
appUser = AppUser.objects.get(user_id=request.user.id)
group = appUser.group
appUsers = group.appuser_set.all()
emails = []
for x in appUsers:
emails.append(x.user.email)
Alternatively I could write a raw SQL join to do it but suspect the Django ORM is capable.
What's the proper and most efficient way to do this?
Models:
class User(Model):
id = IntegerField()
username = CharField()
email = CharField()
class Meta:
db_table = "auth_user"
class AppUser(Model):
user = OneToOneField(User, primary_key=True)
group = ForeignKey('Group', null=True, on_delete=SET_NULL)
zip = CharField()
class Meta:
db_table = "app_users"
class Group(Model):
creator = ForeignKey(AppUser, related_name='+')
created = DateTimeField()
name = CharField()
class Meta:
db_table = "groups"
The trick is to always start from the model you actually want to fetch. In this case, you want to fetch emails, which is a field on the User model. So, start with that model, and use the double-underscore syntax to follow the relationships to Group:
users = User.objects.filter(appuser__group_id=group_id)
In this case, you actually only need a single JOIN, because group_id is a field on AppUser itself (it's the underlying db field for the group ForeignKey). If you had the group name, you would need two joins:
users = User.objects.filter(appuser__group__name=group_name)

Categories

Resources